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 :
71 : #include <boost/scoped_ptr.hpp>
72 :
73 : #define ENV_NEWDOC RET_OK
74 : #define ENV_INSERT RET_USER
75 :
76 : // Function used for labels and envelopes in applab.cxx and appenv.cxx
77 0 : OUString InsertLabEnvText( SwWrtShell& rSh, SwFldMgr& rFldMgr, const OUString& rText )
78 : {
79 0 : OUString sRet;
80 0 : OUString aText(comphelper::string::remove(rText, '\r'));
81 :
82 0 : sal_Int32 nTokenPos = 0;
83 0 : while( -1 != nTokenPos )
84 : {
85 0 : OUString aLine = aText.getToken( 0, '\n', nTokenPos );
86 0 : while ( !aLine.isEmpty() )
87 : {
88 0 : OUString sTmpText;
89 0 : bool bField = false;
90 :
91 0 : sal_Int32 nPos = aLine.indexOf( '<' );
92 0 : if (0 != nPos)
93 : {
94 0 : sal_Int32 const nCopy((nPos != -1) ? nPos : aLine.getLength());
95 0 : sTmpText = aLine.copy(0, nCopy);
96 0 : aLine = aLine.copy(nCopy);
97 : }
98 : else
99 : {
100 0 : nPos = aLine.indexOf( '>' );
101 0 : if ( nPos == -1 )
102 : {
103 0 : sTmpText = aLine;
104 0 : aLine = "";
105 : }
106 : else
107 : {
108 0 : sTmpText = aLine.copy( 0, nPos + 1);
109 0 : aLine = aLine.copy( nPos + 1);
110 :
111 : // Database fields must contain at least 3 points!
112 0 : OUString sDBName( sTmpText.copy( 1, sTmpText.getLength() - 2));
113 0 : sal_uInt16 nCnt = comphelper::string::getTokenCount(sDBName, '.');
114 0 : if (nCnt >= 3)
115 : {
116 0 : sDBName = ::ReplacePoint(sDBName, true);
117 0 : SwInsertFld_Data aData(TYP_DBFLD, 0, sDBName, aEmptyOUStr, 0, &rSh );
118 0 : rFldMgr.InsertFld( aData );
119 0 : sRet = sDBName;
120 0 : bField = true;
121 0 : }
122 : }
123 : }
124 0 : if ( !bField )
125 0 : rSh.Insert( sTmpText );
126 0 : }
127 0 : rSh.InsertLineBreak();
128 0 : }
129 0 : rSh.DelLeft(); // Again remove last linebreak
130 :
131 0 : return sRet;
132 : }
133 :
134 0 : static void lcl_CopyCollAttr(SwWrtShell* pOldSh, SwWrtShell* pNewSh, sal_uInt16 nCollId)
135 : {
136 0 : sal_uInt16 nCollCnt = pOldSh->GetTxtFmtCollCount();
137 : SwTxtFmtColl* pColl;
138 0 : for( sal_uInt16 nCnt = 0; nCnt < nCollCnt; ++nCnt )
139 0 : if(nCollId == (pColl = &pOldSh->GetTxtFmtColl(nCnt))->GetPoolFmtId())
140 0 : pNewSh->GetTxtCollFromPool(nCollId)->SetFmtAttr(pColl->GetAttrSet());
141 0 : }
142 :
143 0 : void SwModule::InsertEnv( SfxRequest& rReq )
144 : {
145 : static sal_uInt16 nTitleNo = 0;
146 :
147 : SwDocShell *pMyDocSh;
148 : SfxViewFrame *pFrame;
149 : SwView *pNewView;
150 : SwWrtShell *pOldSh,
151 : *pSh;
152 :
153 : // Get current shell
154 0 : pMyDocSh = (SwDocShell*) SfxObjectShell::Current();
155 0 : pOldSh = pMyDocSh ? pMyDocSh->GetWrtShell() : 0;
156 :
157 : // Create new document (don't show!)
158 0 : SfxObjectShellLock xDocSh( new SwDocShell( SFX_CREATE_MODE_STANDARD ) );
159 0 : xDocSh->DoInitNew( 0 );
160 0 : pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
161 0 : pNewView = (SwView*) pFrame->GetViewShell();
162 0 : pNewView->AttrChangedNotify( &pNewView->GetWrtShell() ); // so that SelectShell is being called
163 0 : pSh = pNewView->GetWrtShellPtr();
164 :
165 0 : OUString aTmp( SW_RES(STR_ENV_TITLE) );
166 0 : aTmp += OUString::number( ++nTitleNo );
167 0 : xDocSh->SetTitle( aTmp );
168 :
169 : // if applicable, copy the old Collections "Sender" and "Receiver" to
170 : // a new document
171 0 : if ( pOldSh )
172 : {
173 0 : ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_JAKETADRESS);
174 0 : ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS);
175 : }
176 :
177 : // Read SwEnvItem from config
178 0 : SwEnvCfgItem aEnvCfg;
179 :
180 : // Check if there's already an envelope.
181 0 : bool bEnvChange = false;
182 :
183 0 : SfxItemSet aSet(GetPool(), FN_ENVELOP, FN_ENVELOP, 0);
184 0 : aSet.Put(aEnvCfg.GetItem());
185 :
186 0 : SfxPrinter* pTempPrinter = pSh->getIDocumentDeviceAccess()->getPrinter( true );
187 0 : if(pOldSh )
188 : {
189 0 : const SwPageDesc& rCurPageDesc = pOldSh->GetPageDesc(pOldSh->GetCurPageDesc());
190 0 : OUString sJacket;
191 0 : SwStyleNameMapper::FillUIName( RES_POOLPAGE_JAKET, sJacket );
192 0 : bEnvChange = rCurPageDesc.GetName() == sJacket;
193 :
194 0 : IDocumentDeviceAccess* pIDDA_old = pOldSh->getIDocumentDeviceAccess();
195 0 : if( pIDDA_old->getPrinter( false ) )
196 : {
197 0 : IDocumentDeviceAccess* pIDDA = pSh->getIDocumentDeviceAccess();
198 0 : pIDDA->setJobsetup( *pIDDA_old->getJobsetup() );
199 : //#69563# if it isn't the same printer then the pointer has been invalidated!
200 0 : pTempPrinter = pIDDA->getPrinter( true );
201 : }
202 0 : pTempPrinter->SetPaperBin(rCurPageDesc.GetMaster().GetPaperBin().GetValue());
203 :
204 : }
205 :
206 0 : Window *pParent = pOldSh ? pOldSh->GetWin() : 0;
207 0 : boost::scoped_ptr<SfxAbstractTabDialog> pDlg;
208 0 : short nMode = ENV_INSERT;
209 :
210 0 : SFX_REQUEST_ARG( rReq, pItem, SwEnvItem, FN_ENVELOP, false );
211 0 : if ( !pItem )
212 : {
213 0 : SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
214 : OSL_ENSURE(pFact, "SwAbstractDialogFactory fail!");
215 :
216 0 : pDlg.reset(pFact->CreateSwEnvDlg( pParent, aSet, pOldSh, pTempPrinter, !bEnvChange ));
217 : OSL_ENSURE(pDlg, "Dialogdiet fail!");
218 0 : nMode = pDlg->Execute();
219 : }
220 : else
221 : {
222 0 : SFX_REQUEST_ARG( rReq, pBoolItem, SfxBoolItem, FN_PARAM_1, false );
223 0 : if ( pBoolItem && pBoolItem->GetValue() )
224 0 : nMode = ENV_NEWDOC;
225 : }
226 :
227 0 : if (nMode == ENV_NEWDOC || nMode == ENV_INSERT)
228 : {
229 0 : SwWait aWait( (SwDocShell&)*xDocSh, true );
230 :
231 : // Read dialog and save item to config
232 0 : const SwEnvItem& rItem = pItem ? *pItem : (const SwEnvItem&) pDlg->GetOutputItemSet()->Get(FN_ENVELOP);
233 0 : aEnvCfg.GetItem() = rItem;
234 0 : aEnvCfg.Commit();
235 :
236 : // When we print we take the Jobsetup that is set up in the dialog.
237 : // Information has to be set here, before a possible destruction of
238 : // the new shell because the shell's printer has been handed to the
239 : // dialog.
240 0 : if ( nMode != ENV_NEWDOC )
241 : {
242 : OSL_ENSURE(pOldSh, "No document - wasn't 'Insert' disabled???");
243 0 : SvxPaperBinItem aItem( RES_PAPER_BIN );
244 0 : aItem.SetValue((sal_uInt8)pSh->getIDocumentDeviceAccess()->getPrinter(true)->GetPaperBin());
245 0 : pOldSh->GetPageDescFromPool(RES_POOLPAGE_JAKET)->GetMaster().SetFmtAttr(aItem);
246 : }
247 :
248 0 : SwWrtShell *pTmp = nMode == ENV_INSERT ? pOldSh : pSh;
249 0 : const SwPageDesc* pFollow = 0;
250 0 : SwTxtFmtColl *pSend = pTmp->GetTxtCollFromPool( RES_POOLCOLL_SENDADRESS ),
251 0 : *pAddr = pTmp->GetTxtCollFromPool( RES_POOLCOLL_JAKETADRESS);
252 0 : const OUString sSendMark = pSend->GetName();
253 0 : const OUString sAddrMark = pAddr->GetName();
254 :
255 0 : if (nMode == ENV_INSERT)
256 : {
257 :
258 0 : SetView(&pOldSh->GetView()); // Set pointer to top view
259 :
260 : // Delete new document
261 0 : xDocSh->DoClose();
262 0 : pSh = pOldSh;
263 : //#i4251# selected text or objects in the document should
264 : //not be deleted on inserting envelopes
265 0 : pSh->EnterStdMode();
266 : // Here it goes (insert)
267 0 : pSh->StartUndo(UNDO_UI_INSERT_ENVELOPE, NULL);
268 0 : pSh->StartAllAction();
269 0 : pSh->SttEndDoc(sal_True);
270 :
271 0 : if (bEnvChange)
272 : {
273 : // followup template: page 2
274 0 : pFollow = pSh->GetPageDesc(pSh->GetCurPageDesc()).GetFollow();
275 :
276 : // Delete text from the first page
277 0 : if ( !pSh->SttNxtPg(sal_True) )
278 0 : pSh->EndPg(sal_True);
279 0 : pSh->DelRight();
280 : // Delete frame of the first page
281 0 : if ( pSh->GotoFly(sSendMark) )
282 : {
283 0 : pSh->EnterSelFrmMode();
284 0 : pSh->DelRight();
285 : }
286 0 : if ( pSh->GotoFly(sAddrMark) )
287 : {
288 0 : pSh->EnterSelFrmMode();
289 0 : pSh->DelRight();
290 : }
291 0 : pSh->SttEndDoc(sal_True);
292 : }
293 : else
294 : // Followup template: page 1
295 0 : pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
296 :
297 : // Insert page break
298 0 : if ( pSh->IsCrsrInTbl() )
299 : {
300 0 : pSh->SplitNode();
301 0 : pSh->Right( CRSR_SKIP_CHARS, sal_False, 1, sal_False );
302 0 : SfxItemSet aBreakSet( pSh->GetAttrPool(), RES_BREAK, RES_BREAK, 0 );
303 0 : aBreakSet.Put( SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) );
304 0 : pSh->SetTblAttr( aBreakSet );
305 : }
306 : else
307 0 : pSh->InsertPageBreak(0, boost::none);
308 0 : pSh->SttEndDoc(sal_True);
309 : }
310 : else
311 : {
312 0 : pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
313 : // Let's go (print)
314 0 : pSh->StartAllAction();
315 0 : pSh->DoUndo(sal_False);
316 :
317 : // Again, copy the new collections "Sender" and "Receiver" to
318 : // a new document
319 0 : if ( pOldSh )
320 : {
321 0 : ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_JAKETADRESS);
322 0 : ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS);
323 : }
324 : }
325 :
326 0 : SET_CURR_SHELL(pSh);
327 0 : pSh->SetNewDoc(); // Avoid performance problems
328 :
329 : // Remember Flys of this site
330 0 : std::vector<SwFrmFmt*> aFlyArr;
331 0 : if( ENV_NEWDOC != nMode && !bEnvChange )
332 0 : pSh->GetPageObjs( aFlyArr );
333 :
334 : // Get page description
335 0 : SwPageDesc* pDesc = pSh->GetPageDescFromPool(RES_POOLPAGE_JAKET);
336 0 : SwFrmFmt& rFmt = pDesc->GetMaster();
337 :
338 0 : Printer *pPrt = pSh->getIDocumentDeviceAccess()->getPrinter( true );
339 :
340 : // Borders (are put together by Shift-Offset and alignment)
341 0 : Size aPaperSize = pPrt->PixelToLogic( pPrt->GetPaperSizePixel(),
342 0 : MAP_TWIP);
343 0 : if ( !aPaperSize.Width() && !aPaperSize.Height() )
344 0 : aPaperSize = SvxPaperInfo::GetPaperSize(PAPER_A4);
345 0 : if ( aPaperSize.Width() > aPaperSize.Height() )
346 0 : Swap( aPaperSize );
347 :
348 0 : long lLeft = rItem.lShiftRight,
349 0 : lUpper = rItem.lShiftDown;
350 :
351 0 : sal_uInt16 nPageW = (sal_uInt16) std::max(rItem.lWidth, rItem.lHeight),
352 0 : nPageH = (sal_uInt16) std::min(rItem.lWidth, rItem.lHeight);
353 :
354 0 : switch (rItem.eAlign)
355 : {
356 0 : case ENV_HOR_LEFT: break;
357 0 : case ENV_HOR_CNTR: lLeft += std::max(0L, long(aPaperSize.Width() - nPageW)) / 2;
358 0 : break;
359 0 : case ENV_HOR_RGHT: lLeft += std::max(0L, long(aPaperSize.Width() - nPageW));
360 0 : break;
361 0 : case ENV_VER_LEFT: lUpper += std::max(0L, long(aPaperSize.Width() - nPageH));
362 0 : break;
363 0 : case ENV_VER_CNTR: lUpper += std::max(0L, long(aPaperSize.Width() - nPageH)) / 2;
364 0 : break;
365 0 : case ENV_VER_RGHT: break;
366 : }
367 0 : SvxLRSpaceItem aLRMargin( RES_LR_SPACE );
368 0 : SvxULSpaceItem aULMargin( RES_UL_SPACE );
369 0 : aLRMargin.SetLeft ((sal_uInt16) lLeft );
370 0 : aULMargin.SetUpper((sal_uInt16) lUpper);
371 0 : aLRMargin.SetRight(0);
372 0 : aULMargin.SetLower(0);
373 0 : rFmt.SetFmtAttr(aLRMargin);
374 0 : rFmt.SetFmtAttr(aULMargin);
375 :
376 : // Header and footer
377 0 : rFmt.SetFmtAttr(SwFmtHeader(sal_False));
378 0 : pDesc->ChgHeaderShare(sal_False);
379 0 : rFmt.SetFmtAttr(SwFmtFooter(sal_False));
380 0 : pDesc->ChgFooterShare(sal_False);
381 :
382 : // Page numbering
383 0 : pDesc->SetUseOn(nsUseOnPage::PD_ALL);
384 :
385 : // Page size
386 : rFmt.SetFmtAttr(SwFmtFrmSize(ATT_FIX_SIZE,
387 0 : nPageW + lLeft, nPageH + lUpper));
388 :
389 : // Set type of page numbering
390 0 : SvxNumberType aType;
391 0 : aType.SetNumberingType(SVX_NUM_NUMBER_NONE);
392 0 : pDesc->SetNumType(aType);
393 :
394 : // Followup template
395 0 : if (pFollow)
396 0 : pDesc->SetFollow(pFollow);
397 :
398 : // Landscape
399 0 : pDesc->SetLandscape( rItem.eAlign >= ENV_VER_LEFT &&
400 0 : rItem.eAlign <= ENV_VER_RGHT);
401 :
402 : // Apply page description
403 :
404 : sal_uInt16 nPos;
405 : pSh->FindPageDescByName( pDesc->GetName(),
406 : sal_False,
407 0 : &nPos );
408 :
409 0 : pSh->ChgPageDesc( nPos, *pDesc);
410 0 : pSh->ChgCurPageDesc(*pDesc);
411 :
412 : // Insert Frame
413 0 : SwFlyFrmAttrMgr aMgr(sal_False, pSh, FRMMGR_TYPE_ENVELP);
414 0 : SwFldMgr aFldMgr;
415 0 : aMgr.SetHeightSizeType(ATT_VAR_SIZE);
416 :
417 : // Overwrite defaults!
418 0 : aMgr.GetAttrSet().Put( SvxBoxItem(RES_BOX) );
419 0 : aMgr.SetULSpace( 0L, 0L );
420 0 : aMgr.SetLRSpace( 0L, 0L );
421 :
422 : // Sender
423 0 : if (rItem.bSend)
424 : {
425 0 : pSh->SttEndDoc(sal_True);
426 : aMgr.InsertFlyFrm(FLY_AT_PAGE,
427 : Point(rItem.lSendFromLeft + lLeft, rItem.lSendFromTop + lUpper),
428 0 : Size (rItem.lAddrFromLeft - rItem.lSendFromLeft, 0));
429 :
430 0 : pSh->EnterSelFrmMode();
431 0 : pSh->SetFlyName(sSendMark);
432 0 : pSh->UnSelectFrm();
433 0 : pSh->LeaveSelFrmMode();
434 0 : pSh->SetTxtFmtColl( pSend );
435 0 : InsertLabEnvText( *pSh, aFldMgr, rItem.aSendText );
436 0 : aMgr.UpdateAttrMgr();
437 : }
438 :
439 : // Addressee
440 0 : pSh->SttEndDoc(sal_True);
441 :
442 : aMgr.InsertFlyFrm(FLY_AT_PAGE,
443 : Point(rItem.lAddrFromLeft + lLeft, rItem.lAddrFromTop + lUpper),
444 0 : Size (nPageW - rItem.lAddrFromLeft - 566, 0));
445 0 : pSh->EnterSelFrmMode();
446 0 : pSh->SetFlyName(sAddrMark);
447 0 : pSh->UnSelectFrm();
448 0 : pSh->LeaveSelFrmMode();
449 0 : pSh->SetTxtFmtColl( pAddr );
450 0 : InsertLabEnvText(*pSh, aFldMgr, rItem.aAddrText);
451 :
452 : // Move Flys to the "old" pages
453 0 : if (!aFlyArr.empty())
454 0 : pSh->SetPageObjsNewPage(aFlyArr, 1);
455 :
456 : // Finished
457 0 : pSh->SttEndDoc(sal_True);
458 :
459 0 : pSh->EndAllAction();
460 :
461 0 : if (nMode == ENV_NEWDOC)
462 0 : pSh->DoUndo(sal_True);
463 : else
464 0 : pSh->EndUndo(UNDO_UI_INSERT_ENVELOPE);
465 :
466 0 : if (nMode == ENV_NEWDOC)
467 : {
468 0 : pFrame->GetFrame().Appear();
469 :
470 0 : if ( rItem.aAddrText.indexOf('<') >= 0 )
471 : {
472 : static sal_uInt16 const aInva[] =
473 : {
474 : SID_SBA_BRW_UPDATE,
475 : SID_SBA_BRW_INSERT,
476 : SID_SBA_BRW_MERGE,
477 : 0
478 : };
479 0 : pFrame->GetBindings().Invalidate( aInva );
480 :
481 : // Open database beamer
482 0 : ShowDBObj(*pNewView, pSh->GetDBData());
483 : }
484 : }
485 :
486 0 : if ( !pItem )
487 : {
488 0 : rReq.AppendItem( rItem );
489 0 : if ( nMode == ENV_NEWDOC )
490 0 : rReq.AppendItem( SfxBoolItem( FN_PARAM_1, true ) );
491 : }
492 :
493 0 : rReq.Done();
494 : }
495 : else // Abort
496 : {
497 0 : rReq.Ignore();
498 :
499 0 : xDocSh->DoClose();
500 0 : --nTitleNo;
501 :
502 : // Set pointer to top view
503 0 : if (pOldSh)
504 0 : SetView(&pOldSh->GetView());
505 0 : }
506 0 : }
507 :
508 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|