Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <cstdarg>
21 :
22 : #include <hintids.hxx>
23 :
24 : #include <comphelper/string.hxx>
25 : #include <sfx2/request.hxx>
26 : #include <svx/svxids.hrc>
27 :
28 : #include <svtools/svmedit.hxx>
29 : #include <vcl/svapp.hxx>
30 : #include <vcl/wrkwin.hxx>
31 : #include <sfx2/app.hxx>
32 : #include <sfx2/docfac.hxx>
33 : #include <sfx2/printer.hxx>
34 : #include <vcl/msgbox.hxx>
35 : #include <sfx2/dispatch.hxx>
36 : #include <editeng/boxitem.hxx>
37 : #include <editeng/lrspitem.hxx>
38 : #include <editeng/ulspitem.hxx>
39 : #include <editeng/pbinitem.hxx>
40 : #include <editeng/paperinf.hxx>
41 : #include <editeng/formatbreakitem.hxx>
42 : #include <fmthdft.hxx>
43 : #include <swwait.hxx>
44 : #include <paratr.hxx>
45 : #include <swmodule.hxx>
46 : #include <wrtsh.hxx>
47 : #include <view.hxx>
48 : #include <docsh.hxx>
49 : #include <frmatr.hxx>
50 : #include <fldbas.hxx>
51 : #include <swundo.hxx>
52 : #include <IDocumentDeviceAccess.hxx>
53 : #include <dbmgr.hxx>
54 : #include <fmtcol.hxx>
55 : #include <frmmgr.hxx>
56 : #include <fldmgr.hxx>
57 : #include <pagedesc.hxx>
58 : #include <poolfmt.hxx>
59 : #include <expfld.hxx>
60 : #include <SwStyleNameMapper.hxx>
61 : #include <crsskip.hxx>
62 :
63 : #include <cmdid.h>
64 : #include <globals.hrc>
65 : #include <app.hrc>
66 : #include <poolfmt.hrc>
67 : #include "swabstdlg.hxx"
68 : #include "envelp.hrc"
69 : #include "envimg.hxx"
70 : #include <appenv.hxx>
71 :
72 : #include <boost/scoped_ptr.hpp>
73 :
74 : #define ENV_NEWDOC RET_OK
75 : #define ENV_INSERT RET_USER
76 :
77 : // Function used for labels and envelopes in applab.cxx and appenv.cxx
78 0 : OUString InsertLabEnvText( SwWrtShell& rSh, SwFieldMgr& rFieldMgr, const OUString& rText )
79 : {
80 0 : OUString sRet;
81 0 : OUString aText(comphelper::string::remove(rText, '\r'));
82 :
83 0 : sal_Int32 nTokenPos = 0;
84 0 : while( -1 != nTokenPos )
85 : {
86 0 : OUString aLine = aText.getToken( 0, '\n', nTokenPos );
87 0 : while ( !aLine.isEmpty() )
88 : {
89 0 : OUString sTmpText;
90 0 : bool bField = false;
91 :
92 0 : sal_Int32 nPos = aLine.indexOf( '<' );
93 0 : if (0 != nPos)
94 : {
95 0 : sal_Int32 const nCopy((nPos != -1) ? nPos : aLine.getLength());
96 0 : sTmpText = aLine.copy(0, nCopy);
97 0 : aLine = aLine.copy(nCopy);
98 : }
99 : else
100 : {
101 0 : nPos = aLine.indexOf( '>' );
102 0 : if ( nPos == -1 )
103 : {
104 0 : sTmpText = aLine;
105 0 : aLine.clear();
106 : }
107 : else
108 : {
109 0 : sTmpText = aLine.copy( 0, nPos + 1);
110 0 : aLine = aLine.copy( nPos + 1);
111 :
112 : // Database fields must contain at least 3 points!
113 0 : OUString sDBName( sTmpText.copy( 1, sTmpText.getLength() - 2));
114 0 : sal_uInt16 nCnt = comphelper::string::getTokenCount(sDBName, '.');
115 0 : if (nCnt >= 3)
116 : {
117 0 : sDBName = ::ReplacePoint(sDBName, true);
118 0 : SwInsertField_Data aData(TYP_DBFLD, 0, sDBName, aEmptyOUStr, 0, &rSh );
119 0 : rFieldMgr.InsertField( aData );
120 0 : sRet = sDBName;
121 0 : bField = true;
122 0 : }
123 : }
124 : }
125 0 : if ( !bField )
126 0 : rSh.Insert( sTmpText );
127 0 : }
128 0 : rSh.InsertLineBreak();
129 0 : }
130 0 : rSh.DelLeft(); // Again remove last linebreak
131 :
132 0 : return sRet;
133 : }
134 :
135 0 : static void lcl_CopyCollAttr(SwWrtShell* pOldSh, SwWrtShell* pNewSh, sal_uInt16 nCollId)
136 : {
137 0 : sal_uInt16 nCollCnt = pOldSh->GetTextFormatCollCount();
138 0 : for( sal_uInt16 nCnt = 0; nCnt < nCollCnt; ++nCnt )
139 : {
140 0 : SwTextFormatColl* pColl = &pOldSh->GetTextFormatColl(nCnt);
141 0 : if(nCollId == pColl->GetPoolFormatId())
142 0 : pNewSh->GetTextCollFromPool(nCollId)->SetFormatAttr(pColl->GetAttrSet());
143 : }
144 0 : }
145 :
146 0 : void SwModule::InsertEnv( SfxRequest& rReq )
147 : {
148 : static sal_uInt16 nTitleNo = 0;
149 :
150 : SwDocShell *pMyDocSh;
151 : SfxViewFrame *pFrame;
152 : SwView *pNewView;
153 : SwWrtShell *pOldSh,
154 : *pSh;
155 :
156 : // Get current shell
157 0 : pMyDocSh = static_cast<SwDocShell*>( SfxObjectShell::Current());
158 0 : pOldSh = pMyDocSh ? pMyDocSh->GetWrtShell() : 0;
159 :
160 : // Create new document (don't show!)
161 0 : SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD ) );
162 0 : xDocSh->DoInitNew( 0 );
163 0 : pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
164 0 : pNewView = static_cast<SwView*>( pFrame->GetViewShell());
165 0 : pNewView->AttrChangedNotify( &pNewView->GetWrtShell() ); // so that SelectShell is being called
166 0 : pSh = pNewView->GetWrtShellPtr();
167 :
168 0 : OUString aTmp( SW_RES(STR_ENV_TITLE) );
169 0 : aTmp += OUString::number( ++nTitleNo );
170 0 : xDocSh->SetTitle( aTmp );
171 :
172 : // if applicable, copy the old Collections "Sender" and "Receiver" to
173 : // a new document
174 0 : if ( pOldSh )
175 : {
176 0 : ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_JAKETADRESS);
177 0 : ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS);
178 : }
179 :
180 : // Read SwEnvItem from config
181 0 : SwEnvCfgItem aEnvCfg;
182 :
183 : // Check if there's already an envelope.
184 0 : bool bEnvChange = false;
185 :
186 0 : SfxItemSet aSet(GetPool(), FN_ENVELOP, FN_ENVELOP, 0);
187 0 : aSet.Put(aEnvCfg.GetItem());
188 :
189 0 : SfxPrinter* pTempPrinter = pSh->getIDocumentDeviceAccess()->getPrinter( true );
190 0 : if(pOldSh )
191 : {
192 0 : const SwPageDesc& rCurPageDesc = pOldSh->GetPageDesc(pOldSh->GetCurPageDesc());
193 0 : OUString sJacket;
194 0 : SwStyleNameMapper::FillUIName( RES_POOLPAGE_JAKET, sJacket );
195 0 : bEnvChange = rCurPageDesc.GetName() == sJacket;
196 :
197 0 : IDocumentDeviceAccess* pIDDA_old = pOldSh->getIDocumentDeviceAccess();
198 0 : if( pIDDA_old->getPrinter( false ) )
199 : {
200 0 : IDocumentDeviceAccess* pIDDA = pSh->getIDocumentDeviceAccess();
201 0 : pIDDA->setJobsetup( *pIDDA_old->getJobsetup() );
202 : //#69563# if it isn't the same printer then the pointer has been invalidated!
203 0 : pTempPrinter = pIDDA->getPrinter( true );
204 : }
205 0 : pTempPrinter->SetPaperBin(rCurPageDesc.GetMaster().GetPaperBin().GetValue());
206 :
207 : }
208 :
209 0 : vcl::Window *pParent = pOldSh ? pOldSh->GetWin() : 0;
210 0 : boost::scoped_ptr<SfxAbstractTabDialog> pDlg;
211 0 : short nMode = ENV_INSERT;
212 :
213 0 : SFX_REQUEST_ARG( rReq, pItem, SwEnvItem, FN_ENVELOP, false );
214 0 : if ( !pItem )
215 : {
216 0 : SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
217 : OSL_ENSURE(pFact, "SwAbstractDialogFactory fail!");
218 :
219 0 : pDlg.reset(pFact->CreateSwEnvDlg( pParent, aSet, pOldSh, pTempPrinter, !bEnvChange ));
220 : OSL_ENSURE(pDlg, "Dialog creation failed!");
221 0 : nMode = pDlg->Execute();
222 : }
223 : else
224 : {
225 0 : SFX_REQUEST_ARG( rReq, pBoolItem, SfxBoolItem, FN_PARAM_1, false );
226 0 : if ( pBoolItem && pBoolItem->GetValue() )
227 0 : nMode = ENV_NEWDOC;
228 : }
229 :
230 0 : if (nMode == ENV_NEWDOC || nMode == ENV_INSERT)
231 : {
232 0 : SwWait aWait( static_cast<SwDocShell&>(*xDocSh), true );
233 :
234 : // Read dialog and save item to config
235 0 : const SwEnvItem& rItem = pItem ? *pItem : static_cast<const SwEnvItem&>( pDlg->GetOutputItemSet()->Get(FN_ENVELOP) );
236 0 : aEnvCfg.GetItem() = rItem;
237 0 : aEnvCfg.Commit();
238 :
239 : // When we print we take the Jobsetup that is set up in the dialog.
240 : // Information has to be set here, before a possible destruction of
241 : // the new shell because the shell's printer has been handed to the
242 : // dialog.
243 0 : if ( nMode != ENV_NEWDOC )
244 : {
245 : OSL_ENSURE(pOldSh, "No document - wasn't 'Insert' disabled???");
246 0 : SvxPaperBinItem aItem( RES_PAPER_BIN );
247 0 : aItem.SetValue((sal_uInt8)pSh->getIDocumentDeviceAccess()->getPrinter(true)->GetPaperBin());
248 0 : pOldSh->GetPageDescFromPool(RES_POOLPAGE_JAKET)->GetMaster().SetFormatAttr(aItem);
249 : }
250 :
251 0 : SwWrtShell *pTmp = nMode == ENV_INSERT ? pOldSh : pSh;
252 0 : const SwPageDesc* pFollow = 0;
253 0 : SwTextFormatColl *pSend = pTmp->GetTextCollFromPool( RES_POOLCOLL_SENDADRESS ),
254 0 : *pAddr = pTmp->GetTextCollFromPool( RES_POOLCOLL_JAKETADRESS);
255 0 : const OUString sSendMark = pSend->GetName();
256 0 : const OUString sAddrMark = pAddr->GetName();
257 :
258 0 : if (nMode == ENV_INSERT)
259 : {
260 :
261 0 : SetView(&pOldSh->GetView()); // Set pointer to top view
262 :
263 : // Delete new document
264 0 : xDocSh->DoClose();
265 0 : pSh = pOldSh;
266 : //#i4251# selected text or objects in the document should
267 : //not be deleted on inserting envelopes
268 0 : pSh->EnterStdMode();
269 : // Here it goes (insert)
270 0 : pSh->StartUndo(UNDO_UI_INSERT_ENVELOPE, NULL);
271 0 : pSh->StartAllAction();
272 0 : pSh->SttEndDoc(true);
273 :
274 0 : if (bEnvChange)
275 : {
276 : // followup template: page 2
277 0 : pFollow = pSh->GetPageDesc(pSh->GetCurPageDesc()).GetFollow();
278 :
279 : // Delete text from the first page
280 0 : if ( !pSh->SttNxtPg(true) )
281 0 : pSh->EndPg(true);
282 0 : pSh->DelRight();
283 : // Delete frame of the first page
284 0 : if ( pSh->GotoFly(sSendMark) )
285 : {
286 0 : pSh->EnterSelFrmMode();
287 0 : pSh->DelRight();
288 : }
289 0 : if ( pSh->GotoFly(sAddrMark) )
290 : {
291 0 : pSh->EnterSelFrmMode();
292 0 : pSh->DelRight();
293 : }
294 0 : pSh->SttEndDoc(true);
295 : }
296 : else
297 : // Followup template: page 1
298 0 : pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
299 :
300 : // Insert page break
301 0 : if ( pSh->IsCrsrInTable() )
302 : {
303 0 : pSh->SplitNode();
304 0 : pSh->Right( CRSR_SKIP_CHARS, false, 1, false );
305 0 : SfxItemSet aBreakSet( pSh->GetAttrPool(), RES_BREAK, RES_BREAK, 0 );
306 0 : aBreakSet.Put( SvxFormatBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) );
307 0 : pSh->SetTableAttr( aBreakSet );
308 : }
309 : else
310 0 : pSh->InsertPageBreak(0, boost::none);
311 0 : pSh->SttEndDoc(true);
312 : }
313 : else
314 : {
315 0 : pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
316 : // Let's go (print)
317 0 : pSh->StartAllAction();
318 0 : pSh->DoUndo(false);
319 :
320 : // Again, copy the new collections "Sender" and "Receiver" to
321 : // a new document
322 0 : if ( pOldSh )
323 : {
324 0 : ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_JAKETADRESS);
325 0 : ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS);
326 : }
327 : }
328 :
329 0 : SET_CURR_SHELL(pSh);
330 0 : pSh->SetNewDoc(); // Avoid performance problems
331 :
332 : // Remember Flys of this site
333 0 : std::vector<SwFrameFormat*> aFlyArr;
334 0 : if( ENV_NEWDOC != nMode && !bEnvChange )
335 0 : pSh->GetPageObjs( aFlyArr );
336 :
337 : // Get page description
338 0 : SwPageDesc* pDesc = pSh->GetPageDescFromPool(RES_POOLPAGE_JAKET);
339 0 : SwFrameFormat& rFormat = pDesc->GetMaster();
340 :
341 0 : Printer *pPrt = pSh->getIDocumentDeviceAccess()->getPrinter( true );
342 :
343 : // Borders (are put together by Shift-Offset and alignment)
344 0 : Size aPaperSize = pPrt->PixelToLogic( pPrt->GetPaperSizePixel(),
345 0 : MAP_TWIP);
346 0 : if ( !aPaperSize.Width() && !aPaperSize.Height() )
347 0 : aPaperSize = SvxPaperInfo::GetPaperSize(PAPER_A4);
348 0 : if ( aPaperSize.Width() > aPaperSize.Height() )
349 0 : Swap( aPaperSize );
350 :
351 0 : long lLeft = rItem.lShiftRight,
352 0 : lUpper = rItem.lShiftDown;
353 :
354 0 : sal_uInt16 nPageW = (sal_uInt16) std::max(rItem.lWidth, rItem.lHeight),
355 0 : nPageH = (sal_uInt16) std::min(rItem.lWidth, rItem.lHeight);
356 :
357 0 : switch (rItem.eAlign)
358 : {
359 0 : case ENV_HOR_LEFT: break;
360 0 : case ENV_HOR_CNTR: lLeft += std::max(0L, long(aPaperSize.Width() - nPageW)) / 2;
361 0 : break;
362 0 : case ENV_HOR_RGHT: lLeft += std::max(0L, long(aPaperSize.Width() - nPageW));
363 0 : break;
364 0 : case ENV_VER_LEFT: lUpper += std::max(0L, long(aPaperSize.Width() - nPageH));
365 0 : break;
366 0 : case ENV_VER_CNTR: lUpper += std::max(0L, long(aPaperSize.Width() - nPageH)) / 2;
367 0 : break;
368 0 : case ENV_VER_RGHT: break;
369 : }
370 0 : SvxLRSpaceItem aLRMargin( RES_LR_SPACE );
371 0 : SvxULSpaceItem aULMargin( RES_UL_SPACE );
372 0 : aLRMargin.SetLeft ((sal_uInt16) lLeft );
373 0 : aULMargin.SetUpper((sal_uInt16) lUpper);
374 0 : aLRMargin.SetRight(0);
375 0 : aULMargin.SetLower(0);
376 0 : rFormat.SetFormatAttr(aLRMargin);
377 0 : rFormat.SetFormatAttr(aULMargin);
378 :
379 : // Header and footer
380 0 : rFormat.SetFormatAttr(SwFormatHeader(false));
381 0 : pDesc->ChgHeaderShare(false);
382 0 : rFormat.SetFormatAttr(SwFormatFooter(false));
383 0 : pDesc->ChgFooterShare(false);
384 :
385 : // Page numbering
386 0 : pDesc->SetUseOn(nsUseOnPage::PD_ALL);
387 :
388 : // Page size
389 : rFormat.SetFormatAttr(SwFormatFrmSize(ATT_FIX_SIZE,
390 0 : nPageW + lLeft, nPageH + lUpper));
391 :
392 : // Set type of page numbering
393 0 : SvxNumberType aType;
394 0 : aType.SetNumberingType(SVX_NUM_NUMBER_NONE);
395 0 : pDesc->SetNumType(aType);
396 :
397 : // Followup template
398 0 : if (pFollow)
399 0 : pDesc->SetFollow(pFollow);
400 :
401 : // Landscape
402 0 : pDesc->SetLandscape( rItem.eAlign >= ENV_VER_LEFT &&
403 0 : rItem.eAlign <= ENV_VER_RGHT);
404 :
405 : // Apply page description
406 :
407 : size_t nPos;
408 : pSh->FindPageDescByName( pDesc->GetName(),
409 : false,
410 0 : &nPos );
411 :
412 0 : pSh->ChgPageDesc( nPos, *pDesc);
413 0 : pSh->ChgCurPageDesc(*pDesc);
414 :
415 : // Insert Frame
416 0 : SwFlyFrmAttrMgr aMgr(false, pSh, FRMMGR_TYPE_ENVELP);
417 0 : SwFieldMgr aFieldMgr;
418 0 : aMgr.SetHeightSizeType(ATT_VAR_SIZE);
419 :
420 : // Overwrite defaults!
421 0 : aMgr.GetAttrSet().Put( SvxBoxItem(RES_BOX) );
422 0 : aMgr.SetULSpace( 0L, 0L );
423 0 : aMgr.SetLRSpace( 0L, 0L );
424 :
425 : // Sender
426 0 : if (rItem.bSend)
427 : {
428 0 : pSh->SttEndDoc(true);
429 : aMgr.InsertFlyFrm(FLY_AT_PAGE,
430 : Point(rItem.lSendFromLeft + lLeft, rItem.lSendFromTop + lUpper),
431 0 : Size (rItem.lAddrFromLeft - rItem.lSendFromLeft, 0));
432 :
433 0 : pSh->EnterSelFrmMode();
434 0 : pSh->SetFlyName(sSendMark);
435 0 : pSh->UnSelectFrm();
436 0 : pSh->LeaveSelFrmMode();
437 0 : pSh->SetTextFormatColl( pSend );
438 0 : InsertLabEnvText( *pSh, aFieldMgr, rItem.aSendText );
439 0 : aMgr.UpdateAttrMgr();
440 : }
441 :
442 : // Addressee
443 0 : pSh->SttEndDoc(true);
444 :
445 : aMgr.InsertFlyFrm(FLY_AT_PAGE,
446 : Point(rItem.lAddrFromLeft + lLeft, rItem.lAddrFromTop + lUpper),
447 0 : Size (nPageW - rItem.lAddrFromLeft - 566, 0));
448 0 : pSh->EnterSelFrmMode();
449 0 : pSh->SetFlyName(sAddrMark);
450 0 : pSh->UnSelectFrm();
451 0 : pSh->LeaveSelFrmMode();
452 0 : pSh->SetTextFormatColl( pAddr );
453 0 : InsertLabEnvText(*pSh, aFieldMgr, rItem.aAddrText);
454 :
455 : // Move Flys to the "old" pages
456 0 : if (!aFlyArr.empty())
457 0 : pSh->SetPageObjsNewPage(aFlyArr, 1);
458 :
459 : // Finished
460 0 : pSh->SttEndDoc(true);
461 :
462 0 : pSh->EndAllAction();
463 :
464 0 : if (nMode == ENV_NEWDOC)
465 0 : pSh->DoUndo(true);
466 : else
467 0 : pSh->EndUndo(UNDO_UI_INSERT_ENVELOPE);
468 :
469 0 : if (nMode == ENV_NEWDOC)
470 : {
471 0 : pFrame->GetFrame().Appear();
472 :
473 0 : if ( rItem.aAddrText.indexOf('<') >= 0 )
474 : {
475 : static sal_uInt16 const aInva[] =
476 : {
477 : SID_SBA_BRW_UPDATE,
478 : SID_SBA_BRW_INSERT,
479 : SID_SBA_BRW_MERGE,
480 : 0
481 : };
482 0 : pFrame->GetBindings().Invalidate( aInva );
483 :
484 : // Open database beamer
485 0 : ShowDBObj(*pNewView, pSh->GetDBData());
486 : }
487 : }
488 :
489 0 : if ( !pItem )
490 : {
491 0 : rReq.AppendItem( rItem );
492 0 : if ( nMode == ENV_NEWDOC )
493 0 : rReq.AppendItem( SfxBoolItem( FN_PARAM_1, true ) );
494 : }
495 :
496 0 : rReq.Done();
497 : }
498 : else // Abort
499 : {
500 0 : rReq.Ignore();
501 :
502 0 : xDocSh->DoClose();
503 0 : --nTitleNo;
504 :
505 : // Set pointer to top view
506 0 : if (pOldSh)
507 0 : SetView(&pOldSh->GetView());
508 0 : }
509 177 : }
510 :
511 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|