1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 #ifdef SW_DLLIMPLEMENTATION
31 #undef SW_DLLIMPLEMENTATION
32 #endif
33 #include <swtypes.hxx>
34 #include <createaddresslistdialog.hxx>
35 #include <customizeaddresslistdialog.hxx>
36 #include <mmconfigitem.hxx>
37 #include <vcl/scrbar.hxx>
38 #include <vcl/msgbox.hxx>
39 #ifndef _SVT_CONTROLDIMS_HRC_
40 #include <svtools/controldims.hrc>
41 #endif
42 #include <unotools/pathoptions.hxx>
43 #include <sfx2/filedlghelper.hxx>
44 #include <sfx2/docfilt.hxx>
45 #include <sfx2/fcontnr.hxx>
46 #include <sfx2/docfac.hxx>
47 #include <sfx2/docfile.hxx>
48 #include <rtl/textenc.h>
49 #include "com/sun/star/ui/dialogs/TemplateDescription.hpp"
50 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
51 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
52 #include <tools/urlobj.hxx>
53 #include <createaddresslistdialog.hrc>
54 #include <dbui.hrc>
55 #include <helpid.h>
56 #include <unomid.h>
57 
58 
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::ui::dialogs;
61 using ::rtl::OUString;
62 
63 /*-- 19.04.2004 12:19:50---------------------------------------------------
64 
65   -----------------------------------------------------------------------*/
66 class SwAddressControl_Impl : public Control
67 {
68     ScrollBar                       m_aScrollBar;
69     Window                          m_aWindow;
70 
71     ::std::vector<FixedText*>       m_aFixedTexts;
72     ::std::vector<Edit*>            m_aEdits;
73 
74     SwCSVData*                      m_pData;
75     Size                            m_aWinOutputSize;
76     sal_Int32                       m_nLineHeight;
77     sal_uInt32                      m_nCurrentDataSet;
78 
79     bool                            m_bNoDataSet;
80 
81     DECL_LINK(ScrollHdl_Impl, ScrollBar*);
82     DECL_LINK(GotFocusHdl_Impl, Edit*);
83     DECL_LINK(EditModifyHdl_Impl, Edit*);
84 
85     void                MakeVisible(const Rectangle& aRect);
86 
87     virtual long        PreNotify( NotifyEvent& rNEvt );
88     virtual void        Command( const CommandEvent& rCEvt );
89 
90     using Window::SetData;
91 
92 public:
93     SwAddressControl_Impl(Window* pParent, const ResId& rResId );
94     ~SwAddressControl_Impl();
95 
96     void        SetData(SwCSVData& rDBData);
97 
98     void        SetCurrentDataSet(sal_uInt32 nSet);
99     sal_uInt32  GetCurrentDataSet() const { return m_nCurrentDataSet;}
100     void        SetCursorTo(sal_uInt32 nElement);
101 };
102 
103 /*-- 13.04.2004 10:09:42---------------------------------------------------
104 
105   -----------------------------------------------------------------------*/
106 SwAddressControl_Impl::SwAddressControl_Impl(Window* pParent, const ResId& rResId ) :
107     Control(pParent, rResId),
108 #ifdef MSC
109 #pragma warning (disable : 4355)
110 #endif
111     m_aScrollBar(this, ResId(SCR_1,*rResId.GetResMgr())),
112     m_aWindow(this, ResId(WIN_DATA,*rResId.GetResMgr())),
113 #ifdef MSC
114 #pragma warning (default : 4355)
115 #endif
116     m_pData(0),
117     m_aWinOutputSize( m_aWindow.GetOutputSizePixel() ),
118     m_nLineHeight(0),
119     m_nCurrentDataSet(0),
120     m_bNoDataSet(true)
121 {
122     FreeResource();
123     Link aScrollLink = LINK(this, SwAddressControl_Impl, ScrollHdl_Impl);
124     m_aScrollBar.SetScrollHdl(aScrollLink);
125     m_aScrollBar.SetEndScrollHdl(aScrollLink);
126     m_aScrollBar.EnableDrag();
127 
128 }
129 /*-- 13.04.2004 10:09:43---------------------------------------------------
130 
131   -----------------------------------------------------------------------*/
132 SwAddressControl_Impl::~SwAddressControl_Impl()
133 {
134     ::std::vector<FixedText*>::iterator aTextIter;
135     for(aTextIter = m_aFixedTexts.begin(); aTextIter != m_aFixedTexts.end(); ++aTextIter)
136         delete *aTextIter;
137     ::std::vector<Edit*>::iterator aEditIter;
138     for(aEditIter = m_aEdits.begin(); aEditIter != m_aEdits.end(); ++aEditIter)
139         delete *aEditIter;
140 }
141 /*-- 19.04.2004 12:22:41---------------------------------------------------
142 
143   -----------------------------------------------------------------------*/
144 void SwAddressControl_Impl::SetData(SwCSVData& rDBData)
145 {
146     m_pData = &rDBData;
147     //when the address data is updated then remove the controls an build again
148     if(m_aFixedTexts.size())
149     {
150         ::std::vector<FixedText*>::iterator aTextIter;
151         for(aTextIter = m_aFixedTexts.begin(); aTextIter != m_aFixedTexts.end(); ++aTextIter)
152             delete *aTextIter;
153         ::std::vector<Edit*>::iterator aEditIter;
154         for(aEditIter = m_aEdits.begin(); aEditIter != m_aEdits.end(); ++aEditIter)
155             delete *aEditIter;
156         m_aFixedTexts.clear();
157         m_aEdits.clear();
158         m_bNoDataSet = true;
159     }
160     //now create appropriate controls
161 
162     ::std::vector< OUString >::iterator  aHeaderIter;
163 
164     long nFTXPos = m_aWindow.LogicToPixel(Point(RSC_SP_CTRL_X, RSC_SP_CTRL_X), MAP_APPFONT).X();
165     long nFTHeight = m_aWindow.LogicToPixel(Size(RSC_BS_CHARHEIGHT, RSC_BS_CHARHEIGHT), MAP_APPFONT).Height();
166     long nFTWidth = 0;
167 
168     //determine the width of the FixedTexts
169     for(aHeaderIter = m_pData->aDBColumnHeaders.begin();
170                 aHeaderIter != m_pData->aDBColumnHeaders.end();
171                 ++aHeaderIter)
172     {
173         sal_Int32 nTemp = m_aWindow.GetTextWidth(*aHeaderIter);
174         if(nTemp > nFTWidth)
175           nFTWidth = nTemp;
176     }
177     //add some pixels
178     nFTWidth += 2;
179     long nEDXPos = nFTWidth + nFTXPos +
180             m_aWindow.LogicToPixel(Size(RSC_SP_CTRL_DESC_X, RSC_SP_CTRL_DESC_X), MAP_APPFONT).Width();
181     long nEDHeight = m_aWindow.LogicToPixel(Size(RSC_CD_TEXTBOX_HEIGHT, RSC_CD_TEXTBOX_HEIGHT), MAP_APPFONT).Height();
182     long nEDWidth = m_aWinOutputSize.Width() - nEDXPos - nFTXPos;
183     m_nLineHeight = nEDHeight + m_aWindow.LogicToPixel(Size(RSC_SP_CTRL_GROUP_Y, RSC_SP_CTRL_GROUP_Y), MAP_APPFONT).Height();
184 
185     long nEDYPos = m_aWindow.LogicToPixel(Size(RSC_SP_CTRL_DESC_Y, RSC_SP_CTRL_DESC_Y), MAP_APPFONT).Height();
186     long nFTYPos = nEDYPos + nEDHeight - nFTHeight;
187 
188     Link aFocusLink = LINK(this, SwAddressControl_Impl, GotFocusHdl_Impl);
189     Link aEditModifyLink = LINK(this, SwAddressControl_Impl, EditModifyHdl_Impl);
190     Edit* pLastEdit = 0;
191     sal_Int32 nVisibleLines = 0;
192     sal_Int32 nLines = 0;
193     for(aHeaderIter = m_pData->aDBColumnHeaders.begin();
194                 aHeaderIter != m_pData->aDBColumnHeaders.end();
195                 ++aHeaderIter, nEDYPos += m_nLineHeight, nFTYPos += m_nLineHeight, nLines++)
196     {
197         FixedText* pNewFT = new FixedText(&m_aWindow, WB_RIGHT);
198         Edit* pNewED = new Edit(&m_aWindow, WB_BORDER);
199         //set nLines a position identifier - used in the ModifyHdl
200         pNewED->SetData((void*)nLines);
201         pNewED->SetGetFocusHdl(aFocusLink);
202         pNewED->SetModifyHdl(aEditModifyLink);
203 
204         pNewFT->SetPosSizePixel(Point(nFTXPos, nFTYPos), Size(nFTWidth, nFTHeight));
205         pNewED->SetPosSizePixel(Point(nEDXPos, nEDYPos), Size(nEDWidth, nEDHeight));
206         if(nEDYPos + nEDHeight < m_aWinOutputSize.Height())
207             ++nVisibleLines;
208 
209         pNewFT->SetText(*aHeaderIter);
210 
211         pNewFT->Show();
212         pNewED->Show();
213         m_aFixedTexts.push_back(pNewFT);
214         m_aEdits.push_back(pNewED);
215         pLastEdit = pNewED;
216     }
217     //scrollbar adjustment
218     if(pLastEdit)
219     {
220         //the m_aWindow has to be at least as high as the ScrollBar and it must include the last Edit
221         sal_Int32 nContentHeight = pLastEdit->GetPosPixel().Y() + nEDHeight +
222                 m_aWindow.LogicToPixel(Size(RSC_SP_CTRL_GROUP_Y, RSC_SP_CTRL_GROUP_Y), MAP_APPFONT).Height();
223         if(nContentHeight < m_aScrollBar.GetSizePixel().Height())
224         {
225             nContentHeight = m_aScrollBar.GetSizePixel().Height();
226             m_aScrollBar.Enable(sal_False);
227         }
228         else
229         {
230             m_aScrollBar.Enable(sal_True);
231             m_aScrollBar.SetRange(Range(0, nLines));
232             m_aScrollBar.SetThumbPos(0);
233             m_aScrollBar.SetVisibleSize(nVisibleLines);
234         }
235         Size aWinOutputSize(m_aWinOutputSize);
236         aWinOutputSize.Height() = nContentHeight;
237         m_aWindow.SetOutputSizePixel(aWinOutputSize);
238 
239     }
240 }
241 /*-- 21.04.2004 11:37:09---------------------------------------------------
242 
243   -----------------------------------------------------------------------*/
244 void SwAddressControl_Impl::SetCurrentDataSet(sal_uInt32 nSet)
245 {
246     if(m_bNoDataSet || m_nCurrentDataSet != nSet)
247     {
248         m_bNoDataSet = false;
249         m_nCurrentDataSet = nSet;
250         DBG_ASSERT(m_pData->aDBData.size() > m_nCurrentDataSet, "wrong data set index");
251         if(m_pData->aDBData.size() > m_nCurrentDataSet)
252         {
253             ::std::vector<Edit*>::iterator aEditIter;
254             sal_uInt32 nIndex = 0;
255             for(aEditIter = m_aEdits.begin(); aEditIter != m_aEdits.end(); ++aEditIter, ++nIndex)
256             {
257                 DBG_ASSERT(nIndex < m_pData->aDBData[m_nCurrentDataSet].size(),
258                             "number of colums doesn't match number of Edits");
259                 (*aEditIter)->SetText(m_pData->aDBData[m_nCurrentDataSet][nIndex]);
260             }
261         }
262     }
263 }
264 
265 /*-- 19.04.2004 14:17:50---------------------------------------------------
266 
267   -----------------------------------------------------------------------*/
268 IMPL_LINK(SwAddressControl_Impl, ScrollHdl_Impl, ScrollBar*, pScroll)
269 {
270     long nThumb = pScroll->GetThumbPos();
271     m_aWindow.SetPosPixel(Point(0, - (m_nLineHeight * nThumb)));
272 
273     return 0;
274 }
275 /*-- 19.04.2004 16:16:25---------------------------------------------------
276 
277   -----------------------------------------------------------------------*/
278 IMPL_LINK(SwAddressControl_Impl, GotFocusHdl_Impl, Edit*, pEdit)
279 {
280     if(0 != (GETFOCUS_TAB & pEdit->GetGetFocusFlags()))
281     {
282         Rectangle aRect(pEdit->GetPosPixel(), pEdit->GetSizePixel());
283         MakeVisible(aRect);
284     }
285     return 0;
286 }
287 /*-- 21.04.2004 14:56:54---------------------------------------------------
288 
289   -----------------------------------------------------------------------*/
290 void SwAddressControl_Impl::MakeVisible(const Rectangle & rRect)
291 {
292     long nThumb = m_aScrollBar.GetThumbPos();
293     //determine range of visible positions
294     long nMinVisiblePos = - m_aWindow.GetPosPixel().Y();
295     long nMaxVisiblePos = m_aScrollBar.GetSizePixel().Height() + nMinVisiblePos;
296     if( rRect.TopLeft().Y() < nMinVisiblePos)
297     {
298         nThumb -= 1 + ((nMinVisiblePos - rRect.TopLeft().Y()) / m_nLineHeight);
299     }
300     else if(rRect.BottomLeft().Y() > nMaxVisiblePos)
301     {
302         nThumb += 1 + ((nMaxVisiblePos - rRect.BottomLeft().Y()) / m_nLineHeight);
303     }
304     if(nThumb != m_aScrollBar.GetThumbPos())
305     {
306         m_aScrollBar.SetThumbPos(nThumb);
307         ScrollHdl_Impl(&m_aScrollBar);
308     }
309 }
310 /*-- 19.04.2004 16:16:25---------------------------------------------------
311     copy data changes into database
312   -----------------------------------------------------------------------*/
313 IMPL_LINK(SwAddressControl_Impl, EditModifyHdl_Impl, Edit*, pEdit)
314 {
315     //get the data element number of the current set
316     sal_Int32 nIndex = (sal_Int32)(sal_IntPtr)pEdit->GetData();
317     //get the index of the set
318     DBG_ASSERT(m_pData->aDBData.size() > m_nCurrentDataSet, "wrong data set index" );
319     if(m_pData->aDBData.size() > m_nCurrentDataSet)
320     {
321         m_pData->aDBData[m_nCurrentDataSet][nIndex] = pEdit->GetText();
322     }
323     return 0;
324 }
325 /*-- 21.04.2004 14:51:54---------------------------------------------------
326 
327   -----------------------------------------------------------------------*/
328 void SwAddressControl_Impl::SetCursorTo(sal_uInt32 nElement)
329 {
330     if(nElement < m_aEdits.size())
331     {
332         Edit* pEdit = m_aEdits[nElement];
333         pEdit->GrabFocus();
334         Rectangle aRect(pEdit->GetPosPixel(), pEdit->GetSizePixel());
335         MakeVisible(aRect);
336     }
337 
338 }
339 /*-- 19.04.2004 16:16:25---------------------------------------------------
340 
341   -----------------------------------------------------------------------*/
342 void SwAddressControl_Impl::Command( const CommandEvent& rCEvt )
343 {
344     switch ( rCEvt.GetCommand() )
345     {
346         case COMMAND_WHEEL:
347         case COMMAND_STARTAUTOSCROLL:
348         case COMMAND_AUTOSCROLL:
349         {
350             const CommandWheelData* pWheelData = rCEvt.GetWheelData();
351             if(pWheelData && !pWheelData->IsHorz() && COMMAND_WHEEL_ZOOM != pWheelData->GetMode())
352             {
353                 HandleScrollCommand( rCEvt, 0, &m_aScrollBar );
354             }
355         }
356         break;
357         default:
358             Control::Command(rCEvt);
359     }
360 }
361 /*-- 19.04.2004 16:16:25---------------------------------------------------
362 
363   -----------------------------------------------------------------------*/
364 long SwAddressControl_Impl::PreNotify( NotifyEvent& rNEvt )
365 {
366     if(rNEvt.GetType() == EVENT_COMMAND)
367     {
368         const CommandEvent* pCEvt = rNEvt.GetCommandEvent();
369         sal_uInt16 nCmd = pCEvt->GetCommand();
370         if( COMMAND_WHEEL == nCmd )
371         {
372             Command(*pCEvt);
373             return 1;
374         }
375     }
376     return Control::PreNotify(rNEvt);
377 }
378 /*-- 13.04.2004 10:08:59---------------------------------------------------
379 
380   -----------------------------------------------------------------------*/
381 SwCreateAddressListDialog::SwCreateAddressListDialog(
382         Window* pParent, const String& rURL, SwMailMergeConfigItem& rConfig) :
383     SfxModalDialog(pParent, SW_RES(DLG_MM_CREATEADDRESSLIST)),
384 #ifdef MSC
385 #pragma warning (disable : 4355)
386 #endif
387     m_aAddressInformation( this, SW_RES(  FI_ADDRESSINFORMATION)),
388     m_pAddressControl(new SwAddressControl_Impl(this, SW_RES(CT_ADDRESS))),
389     m_aNewPB( this, SW_RES(               PB_NEW)),
390     m_aDeletePB( this, SW_RES(            PB_DELETE)),
391     m_aFindPB( this, SW_RES(              PB_FIND)),
392     m_aCustomizePB( this, SW_RES(         PB_CUSTOMIZE)),
393 
394     m_aViewEntriesFI( this, SW_RES(       FI_VIEWENTRIES)),
395     m_aStartPB( this, SW_RES(             PB_START)),
396     m_aPrevPB( this, SW_RES(              PB_PREV)),
397     m_aSetNoNF( this, SW_RES(             NF_SETNO)),
398     m_aNextPB( this, SW_RES(              PB_NEXT  )),
399     m_aEndPB( this, SW_RES(               PB_END)),
400 
401     m_aSeparatorFL( this, SW_RES(         FL_SEPARATOR)),
402 
403     m_aOK( this, SW_RES(                  PB_OK)),
404     m_aCancel( this, SW_RES(              PB_CANCEL)),
405     m_aHelp( this, SW_RES(                PB_HELP)),
406 #ifdef MSC
407 #pragma warning (default : 4355)
408 #endif
409     m_sAddressListFilterName( SW_RES(    ST_FILTERNAME)),
410     m_sURL(rURL),
411     m_pCSVData( new SwCSVData ),
412     m_pFindDlg(0)
413 {
414     FreeResource();
415     m_aNewPB.SetClickHdl(LINK(this, SwCreateAddressListDialog, NewHdl_Impl));
416     m_aDeletePB.SetClickHdl(LINK(this, SwCreateAddressListDialog, DeleteHdl_Impl));
417     m_aFindPB.SetClickHdl(LINK(this, SwCreateAddressListDialog, FindHdl_Impl));
418     m_aCustomizePB.SetClickHdl(LINK(this, SwCreateAddressListDialog, CustomizeHdl_Impl));
419     m_aOK.SetClickHdl(LINK(this, SwCreateAddressListDialog, OkHdl_Impl));
420 
421     Link aLk = LINK(this, SwCreateAddressListDialog, DBCursorHdl_Impl);
422     m_aStartPB.SetClickHdl(aLk);
423     m_aPrevPB.SetClickHdl(aLk);
424     m_aSetNoNF.SetModifyHdl(LINK(this, SwCreateAddressListDialog, DBNumCursorHdl_Impl));
425     m_aNextPB.SetClickHdl(aLk);
426     m_aEndPB.SetClickHdl(aLk);
427 
428     if(m_sURL.Len())
429     {
430         //file exists, has to be loaded here
431         SfxMedium aMedium( m_sURL, STREAM_READ, sal_True );
432         SvStream* pStream = aMedium.GetInStream();
433         if(pStream)
434         {
435             pStream->SetLineDelimiter( LINEEND_LF );
436             pStream->SetStreamCharSet(RTL_TEXTENCODING_UTF8);
437 
438             OUString sSemi(';');
439             OUString sQuote('"');
440             String sTempMiddle(sQuote);
441             sTempMiddle += sal_Unicode(9);
442             OUString sMiddle(sTempMiddle);
443 
444             String sLine;
445             sal_Bool bRead = pStream->ReadUniOrByteStringLine( sLine, RTL_TEXTENCODING_UTF8 );
446 
447             if(bRead)
448             {
449                 //header line
450                 xub_StrLen nHeaders = sLine.GetTokenCount('\t');
451                 xub_StrLen nIndex = 0;
452                 for( xub_StrLen nToken = 0; nToken < nHeaders; ++nToken)
453                 {
454                     String sHeader = sLine.GetToken( 0, '\t', nIndex );
455                     DBG_ASSERT(sHeader.Len() > 2 &&
456                             sHeader.GetChar(0) == '\"' && sHeader.GetChar(sHeader.Len() - 1) == '\"',
457                             "Wrong format of header");
458                     if(sHeader.Len() > 2)
459                     {
460                         m_pCSVData->aDBColumnHeaders.push_back( sHeader.Copy(1, sHeader.Len() -2));
461                     }
462                 }
463             }
464             while(pStream->ReadUniOrByteStringLine( sLine, RTL_TEXTENCODING_UTF8 ))
465             {
466                 ::std::vector<OUString> aNewData;
467                 //analyze data line
468                 xub_StrLen nDataCount = sLine.GetTokenCount('\t');
469                 xub_StrLen nIndex = 0;
470                 for( xub_StrLen nToken = 0; nToken < nDataCount; ++nToken)
471                 {
472                     String sData = sLine.GetToken( 0, '\t', nIndex );
473                     DBG_ASSERT(sData.Len() >= 2 &&
474                                 sData.GetChar(0) == '\"' && sData.GetChar(sData.Len() - 1) == '\"',
475                             "Wrong format of line");
476                     if(sData.Len() >= 2)
477                         aNewData.push_back(sData.Copy(1, sData.Len() - 2));
478                     else
479                         aNewData.push_back(sData);
480                 }
481                 m_pCSVData->aDBData.push_back( aNewData );
482             }
483         }
484     }
485     else
486     {
487         //database has to be created
488         const ResStringArray& rAddressHeader = rConfig.GetDefaultAddressHeaders();
489         sal_uInt32 nCount = rAddressHeader.Count();
490         for(sal_uInt16 nHeader = 0; nHeader < nCount; ++nHeader)
491             m_pCSVData->aDBColumnHeaders.push_back( rAddressHeader.GetString(nHeader));
492         ::std::vector<OUString> aNewData;
493         String sTemp;
494         aNewData.insert(aNewData.begin(), nCount, sTemp);
495         m_pCSVData->aDBData.push_back(aNewData);
496     }
497     //now fill the address control
498     m_pAddressControl->SetData(*m_pCSVData);
499     m_pAddressControl->SetCurrentDataSet(0);
500     m_aSetNoNF.SetMax(m_pCSVData->aDBData.size());
501     UpdateButtons();
502 }
503 /*-- 13.04.2004 10:08:59---------------------------------------------------
504 
505   -----------------------------------------------------------------------*/
506 SwCreateAddressListDialog::~SwCreateAddressListDialog()
507 {
508     delete m_pAddressControl;
509     delete m_pCSVData;
510     delete m_pFindDlg;
511 }
512 /*-- 13.04.2004 10:08:59---------------------------------------------------
513     add a new data set of empty strings and set the address input control
514     to that new set
515   -----------------------------------------------------------------------*/
516 IMPL_LINK(SwCreateAddressListDialog, NewHdl_Impl, PushButton*, EMPTYARG)
517 {
518     sal_uInt32 nCurrent = m_pAddressControl->GetCurrentDataSet();
519     ::std::vector<OUString> aNewData;
520     String sTemp;
521     aNewData.insert(aNewData.begin(), m_pCSVData->aDBColumnHeaders.size(), sTemp);
522     m_pCSVData->aDBData.insert(m_pCSVData->aDBData.begin() + ++nCurrent, aNewData);
523     m_aSetNoNF.SetMax(m_pCSVData->aDBData.size());
524     //the NumericField start at 1
525     m_aSetNoNF.SetValue(nCurrent + 1);
526     //the address control starts at 0
527     m_pAddressControl->SetCurrentDataSet(nCurrent);
528     UpdateButtons();
529     return 0;
530 }
531 /*-- 13.04.2004 10:09:00---------------------------------------------------
532 
533   -----------------------------------------------------------------------*/
534 IMPL_LINK(SwCreateAddressListDialog, DeleteHdl_Impl, PushButton*, EMPTYARG)
535 {
536     sal_uInt32 nCurrent = m_pAddressControl->GetCurrentDataSet();
537     if(m_pCSVData->aDBData.size() > 1)
538     {
539         m_pCSVData->aDBData.erase(m_pCSVData->aDBData.begin() + nCurrent);
540         if(nCurrent)
541             --nCurrent;
542     }
543     else
544     {
545         // if only one set is available then clear the data
546         String sTemp;
547         m_pCSVData->aDBData[0].assign(m_pCSVData->aDBData[0].size(), sTemp);
548         m_aDeletePB.Enable(sal_False);
549     }
550     m_pAddressControl->SetCurrentDataSet(nCurrent);
551     m_aSetNoNF.SetMax(m_pCSVData->aDBData.size());
552     UpdateButtons();
553     return 0;
554 }
555 /*-- 13.04.2004 10:09:00---------------------------------------------------
556 
557   -----------------------------------------------------------------------*/
558 IMPL_LINK(SwCreateAddressListDialog, FindHdl_Impl, PushButton*, EMPTYARG)
559 {
560     if(!m_pFindDlg)
561     {
562         m_pFindDlg = new SwFindEntryDialog(this);
563         ListBox& rColumnBox = m_pFindDlg->GetFieldsListBox();
564         ::std::vector< OUString >::iterator  aHeaderIter;
565         for(aHeaderIter = m_pCSVData->aDBColumnHeaders.begin();
566                     aHeaderIter != m_pCSVData->aDBColumnHeaders.end();
567                     ++aHeaderIter)
568             rColumnBox.InsertEntry(*aHeaderIter);
569         rColumnBox.SelectEntryPos( 0 );
570     }
571     else
572         m_pFindDlg->Show(!m_pFindDlg->IsVisible());
573     return 0;
574 }
575 /*-- 13.04.2004 10:09:00---------------------------------------------------
576 
577   -----------------------------------------------------------------------*/
578 IMPL_LINK(SwCreateAddressListDialog, CustomizeHdl_Impl, PushButton*, pButton)
579 {
580     SwCustomizeAddressListDialog* pDlg = new SwCustomizeAddressListDialog(pButton, *m_pCSVData);
581     if(RET_OK == pDlg->Execute())
582     {
583         delete m_pCSVData;
584         m_pCSVData = pDlg->GetNewData();
585         m_pAddressControl->SetData(*m_pCSVData);
586         m_pAddressControl->SetCurrentDataSet(m_pAddressControl->GetCurrentDataSet());
587     }
588     delete pDlg;
589 
590     //update find dialog
591     if(m_pFindDlg)
592     {
593         ListBox& rColumnBox = m_pFindDlg->GetFieldsListBox();
594         rColumnBox.Clear();
595         ::std::vector< OUString >::iterator  aHeaderIter;
596         for(aHeaderIter = m_pCSVData->aDBColumnHeaders.begin();
597                     aHeaderIter != m_pCSVData->aDBColumnHeaders.end();
598                     ++aHeaderIter)
599             rColumnBox.InsertEntry(*aHeaderIter);
600     }
601     return 0;
602 }
603 /*-- 23.04.2004 09:02:51---------------------------------------------------
604     writes the data into a .csv file
605     encoding is UTF8, separator is tab, strings are enclosed into "
606   -----------------------------------------------------------------------*/
607 IMPL_LINK(SwCreateAddressListDialog, OkHdl_Impl, PushButton*, EMPTYARG)
608 {
609     if(!m_sURL.Len())
610     {
611         sfx2::FileDialogHelper aDlgHelper( TemplateDescription::FILESAVE_SIMPLE, 0 );
612         uno::Reference < XFilePicker > xFP = aDlgHelper.GetFilePicker();
613 
614         String sPath( SvtPathOptions().SubstituteVariable(
615                     String::CreateFromAscii("$(userurl)/database") ));
616         aDlgHelper.SetDisplayDirectory( sPath );
617         uno::Reference< XFilterManager > xFltMgr(xFP, uno::UNO_QUERY);
618         ::rtl::OUString sCSV(C2U("*.csv"));
619         xFltMgr->appendFilter( m_sAddressListFilterName, sCSV );
620         xFltMgr->setCurrentFilter( m_sAddressListFilterName ) ;
621 
622         if( ERRCODE_NONE == aDlgHelper.Execute() )
623         {
624             m_sURL = xFP->getFiles().getConstArray()[0];
625             INetURLObject aResult( m_sURL );
626             aResult.setExtension(String::CreateFromAscii("csv"));
627             m_sURL = aResult.GetMainURL(INetURLObject::NO_DECODE);
628         }
629     }
630     if(m_sURL.Len())
631     {
632         SfxMedium aMedium( m_sURL, STREAM_READWRITE|STREAM_TRUNC, sal_True );
633         SvStream* pStream = aMedium.GetOutStream();
634         pStream->SetLineDelimiter( LINEEND_LF );
635         pStream->SetStreamCharSet(RTL_TEXTENCODING_UTF8);
636 
637         OUString sSemi(';');
638         OUString sQuote('"');
639         String sTempMiddle(sQuote);
640         sTempMiddle += sal_Unicode(9);
641         OUString sMiddle(sTempMiddle);
642         sMiddle += sQuote;
643 
644         //create a string for the header line
645         OUString sLine(sQuote);
646         ::std::vector< OUString >::iterator  aHeaderIter;
647         for(aHeaderIter = m_pCSVData->aDBColumnHeaders.begin();
648                     aHeaderIter != m_pCSVData->aDBColumnHeaders.end();
649                     ++aHeaderIter)
650         {
651             sLine += *aHeaderIter;
652             sLine += sMiddle;
653         }
654         //remove tab and quote
655         sLine = sLine.copy( 0, sLine.getLength() - 2 );
656         pStream->WriteUnicodeOrByteText( sLine, RTL_TEXTENCODING_UTF8 );
657         endl(*pStream);
658 
659         ::std::vector< ::std::vector< OUString > >::iterator aDataIter;
660         for( aDataIter = m_pCSVData->aDBData.begin(); aDataIter != m_pCSVData->aDBData.end(); ++aDataIter)
661         {
662             sLine = sQuote;
663             ::std::vector< OUString >::iterator  aColumnIter;
664             for(aColumnIter = aDataIter->begin(); aColumnIter != aDataIter->end(); ++aColumnIter)
665             {
666                 sLine += *aColumnIter;
667                 sLine += sMiddle;
668             }
669             //remove tab and quote
670             sLine = sLine.copy( 0, sLine.getLength() - 2 );
671             pStream->WriteUnicodeOrByteText( sLine, RTL_TEXTENCODING_UTF8 );
672             endl(*pStream);
673         }
674         aMedium.Commit();
675         EndDialog(RET_OK);
676     }
677 
678     return 0;
679 }
680 /*-- 13.04.2004 10:09:01---------------------------------------------------
681 
682   -----------------------------------------------------------------------*/
683 IMPL_LINK(SwCreateAddressListDialog, DBCursorHdl_Impl, PushButton*, pButton)
684 {
685     sal_uInt32 nValue = static_cast< sal_uInt32 >(m_aSetNoNF.GetValue());
686 
687     if(pButton == &m_aStartPB)
688         nValue = 1;
689     else if(pButton == &m_aPrevPB)
690     {
691         if(nValue > 1)
692             --nValue;
693     }
694     else if(pButton == &m_aNextPB)
695     {
696         if(nValue < (sal_uInt32)m_aSetNoNF.GetMax())
697             ++nValue;
698     }
699     else //m_aEndPB
700         nValue = static_cast< sal_uInt32 >(m_aSetNoNF.GetMax());
701     if(nValue != m_aSetNoNF.GetValue())
702     {
703         m_aSetNoNF.SetValue(nValue);
704         DBNumCursorHdl_Impl(&m_aSetNoNF);
705     }
706     return 0;
707 }
708 /*-- 21.04.2004 12:06:47---------------------------------------------------
709 
710   -----------------------------------------------------------------------*/
711 IMPL_LINK(SwCreateAddressListDialog, DBNumCursorHdl_Impl, NumericField*, EMPTYARG)
712 {
713     m_pAddressControl->SetCurrentDataSet( static_cast< sal_uInt32 >(m_aSetNoNF.GetValue() - 1) );
714     UpdateButtons();
715     return 0;
716 }
717 /*-- 21.04.2004 13:22:27---------------------------------------------------
718 
719   -----------------------------------------------------------------------*/
720 void SwCreateAddressListDialog::UpdateButtons()
721 {
722     sal_uInt32 nCurrent = static_cast< sal_uInt32 >(m_aSetNoNF.GetValue() );
723     sal_uInt32 nSize = (sal_uInt32 )m_pCSVData->aDBData.size();
724     m_aStartPB.Enable(nCurrent != 1);
725     m_aPrevPB.Enable(nCurrent != 1);
726     m_aNextPB.Enable(nCurrent != nSize);
727     m_aEndPB.Enable(nCurrent != nSize);
728     m_aDeletePB.Enable(nSize > 0);
729 }
730 /*-- 21.04.2004 13:22:27---------------------------------------------------
731 
732   -----------------------------------------------------------------------*/
733 void SwCreateAddressListDialog::Find(const String& rSearch, sal_Int32 nColumn)
734 {
735     OUString sSearch = rSearch;
736     sSearch.toAsciiLowerCase();
737     sal_uInt32 nCurrent = m_pAddressControl->GetCurrentDataSet();
738     //search forward
739     bool bFound = false;
740     sal_uInt32 nStart = nCurrent + 1;
741     sal_uInt32 nEnd = m_pCSVData->aDBData.size();
742     sal_uInt32 nElement = 0;
743     sal_uInt32 nPos = 0;
744     for(short nTemp = 0; nTemp < 2 && !bFound; nTemp++)
745     {
746         for(nPos = nStart; nPos < nEnd; ++nPos)
747         {
748             ::std::vector< OUString> aData = m_pCSVData->aDBData[nPos];
749             if(nColumn >=0)
750                 bFound = -1 != aData[(sal_uInt32)nColumn].toAsciiLowerCase().indexOf(sSearch);
751             else
752             {
753                 for( nElement = 0; nElement < aData.size(); ++nElement)
754                 {
755                     bFound = -1 != aData[nElement].toAsciiLowerCase().indexOf(sSearch);
756                     if(bFound)
757                     {
758                         nColumn = nElement;
759                         break;
760                     }
761                 }
762             }
763             if(bFound)
764                 break;
765         }
766         nStart = 0;
767         nEnd = nCurrent + 1;
768     }
769     if(bFound)
770     {
771         m_pAddressControl->SetCurrentDataSet(nPos);
772         m_aSetNoNF.SetValue( nPos + 1 );
773         UpdateButtons();
774         m_pAddressControl->SetCursorTo(nElement);
775     }
776 }
777 /*-- 13.04.2004 13:48:38---------------------------------------------------
778 
779   -----------------------------------------------------------------------*/
780 SwFindEntryDialog::SwFindEntryDialog(SwCreateAddressListDialog* pParent) :
781     ModelessDialog(pParent, SW_RES(DLG_MM_FIND_ENTRY)),
782 #ifdef MSC
783 #pragma warning (disable : 4355)
784 #endif
785     m_aFindFT( this, SW_RES(      FT_FIND      )),
786     m_aFindED( this, SW_RES(      ED_FIND      )),
787     m_aFindOnlyCB( this, SW_RES(  CB_FINDONLY )),
788     m_aFindOnlyLB( this, SW_RES(  LB_FINDONLY  )),
789     m_aFindPB( this, SW_RES(      PB_FIND)),
790     m_aCancel( this, SW_RES(      PB_CANCEL)),
791     m_aHelp( this, SW_RES(        PB_HELP)),
792 #ifdef MSC
793 #pragma warning (default : 4355)
794 #endif
795    m_pParent(pParent)
796 {
797     FreeResource();
798     m_aFindPB.SetClickHdl(LINK(this, SwFindEntryDialog, FindHdl_Impl));
799     m_aFindED.SetModifyHdl(LINK(this, SwFindEntryDialog, FindEnableHdl_Impl));
800     m_aCancel.SetClickHdl(LINK(this, SwFindEntryDialog, CloseHdl_Impl));
801 }
802 /*-- 13.04.2004 13:48:38---------------------------------------------------
803 
804   -----------------------------------------------------------------------*/
805 SwFindEntryDialog::~SwFindEntryDialog()
806 {
807 }
808 /*-- 21.04.2004 13:37:46---------------------------------------------------
809 
810   -----------------------------------------------------------------------*/
811 IMPL_LINK(SwFindEntryDialog, FindHdl_Impl, PushButton*, EMPTYARG)
812 {
813     sal_Int32 nColumn = -1;
814     if(m_aFindOnlyCB.IsChecked())
815         nColumn = m_aFindOnlyLB.GetSelectEntryPos();
816     if(nColumn != LISTBOX_ENTRY_NOTFOUND)
817         m_pParent->Find(m_aFindED.GetText(), nColumn);
818     return 0;
819 }
820 /*-- 21.04.2004 13:37:46---------------------------------------------------
821 
822   -----------------------------------------------------------------------*/
823 IMPL_LINK(SwFindEntryDialog, FindEnableHdl_Impl, Edit*, EMPTYARG)
824 {
825     m_aFindPB.Enable(m_aFindED.GetText().Len() > 0);
826     return 0;
827 }
828 /*-- 21.04.2004 15:36:36---------------------------------------------------
829 
830   -----------------------------------------------------------------------*/
831 IMPL_LINK(SwFindEntryDialog, CloseHdl_Impl, PushButton*, EMPTYARG)
832 {
833     Show(sal_False);
834     return 0;
835 }
836