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