1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
22 #include <comphelper/string.hxx>
23 #include <sfx2/request.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/printer.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <editeng/boxitem.hxx>
29 #include <editeng/lrspitem.hxx>
30 #include <editeng/ulspitem.hxx>
31 #include <editeng/pbinitem.hxx>
32 #include <editeng/paperinf.hxx>
33 #include <osl/diagnose.h>
34 #include <fmthdft.hxx>
36 #include <swmodule.hxx>
43 #include <IDocumentDeviceAccess.hxx>
44 #include <dialoghelp.hxx>
48 #include <pagedesc.hxx>
49 #include <poolfmt.hxx>
51 #include <SwStyleNameMapper.hxx>
52 #include <fmtpdsc.hxx>
55 #include <strings.hrc>
56 #include <swabstdlg.hxx>
60 #define ENV_NEWDOC RET_OK
61 #define ENV_INSERT RET_USER
63 // Function used for labels and envelopes in applab.cxx and appenv.cxx
64 OUString
InsertLabEnvText( SwWrtShell
& rSh
, SwFieldMgr
& rFieldMgr
, const OUString
& rText
)
67 OUString aText
= rText
.replaceAll("\r", "");
69 sal_Int32 nTokenPos
= 0;
70 while( -1 != nTokenPos
)
72 OUString aLine
= aText
.getToken( 0, '\n', nTokenPos
);
73 while ( !aLine
.isEmpty() )
78 sal_Int32 nPos
= aLine
.indexOf( '<' );
81 sal_Int32
const nCopy((nPos
!= -1) ? nPos
: aLine
.getLength());
82 sTmpText
= aLine
.copy(0, nCopy
);
83 aLine
= aLine
.copy(nCopy
);
87 nPos
= aLine
.indexOf( '>' );
95 sTmpText
= aLine
.copy( 0, nPos
+ 1);
96 aLine
= aLine
.copy( nPos
+ 1);
98 // Database fields must contain at least 3 points!
99 OUString
sDBName( sTmpText
.copy( 1, sTmpText
.getLength() - 2));
100 if (comphelper::string::getTokenCount(sDBName
, '.') >= 3)
102 sDBName
= ::ReplacePoint(sDBName
, true);
103 SwInsertField_Data
aData(SwFieldTypesEnum::Database
, 0, sDBName
, OUString(), 0, &rSh
);
104 rFieldMgr
.InsertField( aData
);
111 rSh
.Insert( sTmpText
);
115 rSh
.DelLeft(); // Again remove last linebreak
120 static void lcl_CopyCollAttr(SwWrtShell
const * pOldSh
, SwWrtShell
* pNewSh
, sal_uInt16 nCollId
)
122 sal_uInt16 nCollCnt
= pOldSh
->GetTextFormatCollCount();
123 for( sal_uInt16 nCnt
= 0; nCnt
< nCollCnt
; ++nCnt
)
125 SwTextFormatColl
* pColl
= &pOldSh
->GetTextFormatColl(nCnt
);
126 if(nCollId
== pColl
->GetPoolFormatId())
127 pNewSh
->GetTextCollFromPool(nCollId
)->SetFormatAttr(pColl
->GetAttrSet());
131 void SwModule::InsertEnv( SfxRequest
& rReq
)
133 static sal_uInt16 nTitleNo
= 0;
135 SwDocShell
*pMyDocSh
;
136 SfxViewFrame
*pFrame
;
142 pMyDocSh
= static_cast<SwDocShell
*>( SfxObjectShell::Current());
143 pOldSh
= pMyDocSh
? pMyDocSh
->GetWrtShell() : nullptr;
145 // Create new document (don't show!)
146 SfxObjectShellLock
xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD
) );
148 pFrame
= SfxViewFrame::LoadHiddenDocument( *xDocSh
, SFX_INTERFACE_NONE
);
149 pNewView
= static_cast<SwView
*>( pFrame
->GetViewShell());
150 pNewView
->AttrChangedNotify(nullptr); // so that SelectShell is being called
151 pSh
= pNewView
->GetWrtShellPtr();
156 OUString aTmp
= SwResId(STR_ENV_TITLE
) + OUString::number( ++nTitleNo
);
157 xDocSh
->SetTitle( aTmp
);
159 // if applicable, copy the old Collections "Sender" and "Receiver" to
163 ::lcl_CopyCollAttr(pOldSh
, pSh
, RES_POOLCOLL_ENVELOPE_ADDRESS
);
164 ::lcl_CopyCollAttr(pOldSh
, pSh
, RES_POOLCOLL_SEND_ADDRESS
);
167 // Read SwEnvItem from config
168 SwEnvCfgItem aEnvCfg
;
170 // Check if there's already an envelope.
171 bool bEnvChange
= false;
173 SfxItemSetFixed
<FN_ENVELOP
, FN_ENVELOP
> aSet(GetPool());
174 aSet
.Put(aEnvCfg
.GetItem());
176 SfxPrinter
* pTempPrinter
= pSh
->getIDocumentDeviceAccess().getPrinter( true );
179 const SwPageDesc
& rCurPageDesc
= pOldSh
->GetPageDesc(pOldSh
->GetCurPageDesc());
181 SwStyleNameMapper::FillUIName( RES_POOLPAGE_ENVELOPE
, sEnvelope
);
182 bEnvChange
= rCurPageDesc
.GetName() == sEnvelope
;
184 IDocumentDeviceAccess
& rIDDA_old
= pOldSh
->getIDocumentDeviceAccess();
185 if( rIDDA_old
.getPrinter( false ) )
187 IDocumentDeviceAccess
& rIDDA
= pSh
->getIDocumentDeviceAccess();
188 rIDDA
.setJobsetup( *rIDDA_old
.getJobsetup() );
189 //#69563# if it isn't the same printer then the pointer has been invalidated!
190 pTempPrinter
= rIDDA
.getPrinter( true );
192 pTempPrinter
->SetPaperBin(rCurPageDesc
.GetMaster().GetPaperBin().GetValue());
196 ScopedVclPtr
<SfxAbstractTabDialog
> pDlg
;
197 short nMode
= ENV_INSERT
;
199 const SwEnvItem
* pItem
= rReq
.GetArg
<SwEnvItem
>(FN_ENVELOP
);
202 SwAbstractDialogFactory
* pFact
= SwAbstractDialogFactory::Create();
203 pDlg
.disposeAndReset(pFact
->CreateSwEnvDlg(GetFrameWeld(pMyDocSh
), aSet
, pOldSh
, pTempPrinter
, !bEnvChange
));
204 nMode
= pDlg
->Execute();
208 const SfxBoolItem
* pBoolItem
= rReq
.GetArg
<SfxBoolItem
>(FN_PARAM_1
);
209 if ( pBoolItem
&& pBoolItem
->GetValue() )
213 if (nMode
== ENV_NEWDOC
|| nMode
== ENV_INSERT
)
215 SwWait
aWait( static_cast<SwDocShell
&>(*xDocSh
), true );
217 // Read dialog and save item to config
218 const SwEnvItem
& rItem
= pItem
? *pItem
: static_cast<const SwEnvItem
&>( pDlg
->GetOutputItemSet()->Get(FN_ENVELOP
) );
219 aEnvCfg
.GetItem() = rItem
;
222 // When we print we take the Jobsetup that is set up in the dialog.
223 // Information has to be set here, before a possible destruction of
224 // the new shell because the shell's printer has been handed to the
226 if ( nMode
!= ENV_NEWDOC
)
228 OSL_ENSURE(pOldSh
, "No document - wasn't 'Insert' disabled???");
229 SvxPaperBinItem
aItem( RES_PAPER_BIN
);
230 aItem
.SetValue(static_cast<sal_uInt8
>(pSh
->getIDocumentDeviceAccess().getPrinter(true)->GetPaperBin()));
231 pOldSh
->GetPageDescFromPool(RES_POOLPAGE_ENVELOPE
)->GetMaster().SetFormatAttr(aItem
);
234 SwWrtShell
*pTmp
= nMode
== ENV_INSERT
? pOldSh
: pSh
;
235 const SwPageDesc
* pFollow
= nullptr;
236 SwTextFormatColl
*pSend
= pTmp
->GetTextCollFromPool(RES_POOLCOLL_SEND_ADDRESS
),
237 *pAddr
= pTmp
->GetTextCollFromPool(RES_POOLCOLL_ENVELOPE_ADDRESS
);
238 const OUString sSendMark
= pSend
->GetName();
239 const OUString sAddrMark
= pAddr
->GetName();
241 if (nMode
== ENV_INSERT
)
244 SetView(&pOldSh
->GetView()); // Set pointer to top view
246 // Delete new document
249 //#i4251# selected text or objects in the document should
250 //not be deleted on inserting envelopes
252 // Here it goes (insert)
253 pSh
->StartUndo(SwUndoId::UI_INSERT_ENVELOPE
);
254 pSh
->StartAllAction();
255 pSh
->SttEndDoc(true);
259 // followup template: page 2
260 pFollow
= pSh
->GetPageDesc(pSh
->GetCurPageDesc()).GetFollow();
262 // Delete text from the first page
263 if ( !pSh
->SttNxtPg(true) )
266 // Delete frame of the first page
267 if ( pSh
->GotoFly(sSendMark
) )
269 pSh
->EnterSelFrameMode();
272 if ( pSh
->GotoFly(sAddrMark
) )
274 pSh
->EnterSelFrameMode();
277 pSh
->SttEndDoc(true);
280 // Followup template: page 1
281 pFollow
= &pSh
->GetPageDesc(pSh
->GetCurPageDesc());
284 if ( pSh
->IsCursorInTable() )
287 pSh
->Right( SwCursorSkipMode::Chars
, false, 1, false );
288 SfxItemSetFixed
<RES_PAGEDESC
, RES_PAGEDESC
> aBreakSet( pSh
->GetAttrPool() );
289 aBreakSet
.Put( SwFormatPageDesc( pFollow
) );
290 pSh
->SetTableAttr( aBreakSet
);
294 OUString
sFollowName(pFollow
->GetName());
295 pSh
->InsertPageBreak(&sFollowName
, std::nullopt
);
297 pSh
->SttEndDoc(true);
301 pFollow
= &pSh
->GetPageDesc(pSh
->GetCurPageDesc());
303 pSh
->StartAllAction();
306 // Again, copy the new collections "Sender" and "Receiver" to
310 ::lcl_CopyCollAttr(pOldSh
, pSh
, RES_POOLCOLL_ENVELOPE_ADDRESS
);
311 ::lcl_CopyCollAttr(pOldSh
, pSh
, RES_POOLCOLL_SEND_ADDRESS
);
315 CurrShell
aCurr(pSh
);
316 pSh
->SetNewDoc(); // Avoid performance problems
318 // Remember Flys of this site
319 std::vector
<SwFrameFormat
*> aFlyArr
;
320 if( ENV_NEWDOC
!= nMode
&& !bEnvChange
)
321 pSh
->GetPageObjs( aFlyArr
);
323 // Get page description
324 SwPageDesc
* pDesc
= pSh
->GetPageDescFromPool(RES_POOLPAGE_ENVELOPE
);
325 SwFrameFormat
& rFormat
= pDesc
->GetMaster();
327 Printer
*pPrt
= pSh
->getIDocumentDeviceAccess().getPrinter( true );
329 // Borders (are put together by Shift-Offset and alignment)
330 Size aPaperSize
= pPrt
->PixelToLogic( pPrt
->GetPaperSizePixel(),
331 MapMode(MapUnit::MapTwip
));
332 if ( !aPaperSize
.Width() && !aPaperSize
.Height() )
333 aPaperSize
= SvxPaperInfo::GetPaperSize(PAPER_A4
);
334 if ( aPaperSize
.Width() > aPaperSize
.Height() )
337 tools::Long lLeft
= rItem
.m_nShiftRight
,
338 lUpper
= rItem
.m_nShiftDown
;
340 sal_uInt16 nPageW
= o3tl::narrowing
<sal_uInt16
>(std::max(rItem
.m_nWidth
, rItem
.m_nHeight
)),
341 nPageH
= o3tl::narrowing
<sal_uInt16
>(std::min(rItem
.m_nWidth
, rItem
.m_nHeight
));
343 switch (rItem
.m_eAlign
)
345 case ENV_HOR_LEFT
: break;
346 case ENV_HOR_CNTR
: lLeft
+= std::max(tools::Long(0), aPaperSize
.Width() - nPageW
) / 2;
348 case ENV_HOR_RGHT
: lLeft
+= std::max(tools::Long(0), aPaperSize
.Width() - nPageW
);
350 case ENV_VER_LEFT
: lUpper
+= std::max(tools::Long(0), aPaperSize
.Width() - nPageH
);
352 case ENV_VER_CNTR
: lUpper
+= std::max(tools::Long(0), aPaperSize
.Width() - nPageH
) / 2;
354 case ENV_VER_RGHT
: break;
356 SvxLRSpaceItem
aLRMargin( RES_LR_SPACE
);
357 SvxULSpaceItem
aULMargin( RES_UL_SPACE
);
358 aLRMargin
.SetLeft (o3tl::narrowing
<sal_uInt16
>(lLeft
) );
359 aULMargin
.SetUpper(o3tl::narrowing
<sal_uInt16
>(lUpper
));
360 aLRMargin
.SetRight(0);
361 aULMargin
.SetLower(0);
362 rFormat
.SetFormatAttr(aLRMargin
);
363 rFormat
.SetFormatAttr(aULMargin
);
366 rFormat
.SetFormatAttr(SwFormatHeader(false));
367 pDesc
->ChgHeaderShare(false);
368 rFormat
.SetFormatAttr(SwFormatFooter(false));
369 pDesc
->ChgFooterShare(false);
372 pDesc
->SetUseOn(UseOnPage::All
);
375 rFormat
.SetFormatAttr(SwFormatFrameSize(SwFrameSize::Fixed
,
376 nPageW
+ lLeft
, nPageH
+ lUpper
));
378 // Set type of page numbering
380 aType
.SetNumberingType(SVX_NUM_NUMBER_NONE
);
381 pDesc
->SetNumType(aType
);
385 pDesc
->SetFollow(pFollow
);
388 pDesc
->SetLandscape( rItem
.m_eAlign
>= ENV_VER_LEFT
&&
389 rItem
.m_eAlign
<= ENV_VER_RGHT
);
391 // Apply page description
394 pSh
->FindPageDescByName( pDesc
->GetName(),
398 pSh
->ChgPageDesc( nPos
, *pDesc
);
399 pSh
->ChgCurPageDesc(*pDesc
);
402 SwFlyFrameAttrMgr
aMgr(false, pSh
, Frmmgr_Type::ENVELP
, nullptr);
403 SwFieldMgr aFieldMgr
;
404 aMgr
.SetHeightSizeType(SwFrameSize::Variable
);
406 // Overwrite defaults!
407 aMgr
.GetAttrSet().Put( SvxBoxItem(RES_BOX
) );
408 aMgr
.SetULSpace( 0, 0 );
409 aMgr
.SetLRSpace( 0, 0 );
414 pSh
->SttEndDoc(true);
415 aMgr
.InsertFlyFrame(RndStdIds::FLY_AT_PAGE
,
416 Point(rItem
.m_nSendFromLeft
+ lLeft
, rItem
.m_nSendFromTop
+ lUpper
),
417 Size (rItem
.m_nAddrFromLeft
- rItem
.m_nSendFromLeft
, 0));
419 pSh
->EnterSelFrameMode();
420 pSh
->SetFlyName(sSendMark
);
421 pSh
->UnSelectFrame();
422 pSh
->LeaveSelFrameMode();
423 pSh
->SetTextFormatColl( pSend
);
424 InsertLabEnvText( *pSh
, aFieldMgr
, rItem
.m_aSendText
);
425 aMgr
.UpdateAttrMgr();
429 pSh
->SttEndDoc(true);
431 aMgr
.InsertFlyFrame(RndStdIds::FLY_AT_PAGE
,
432 Point(rItem
.m_nAddrFromLeft
+ lLeft
, rItem
.m_nAddrFromTop
+ lUpper
),
433 Size (nPageW
- rItem
.m_nAddrFromLeft
- 566, 0));
434 pSh
->EnterSelFrameMode();
435 pSh
->SetFlyName(sAddrMark
);
436 pSh
->UnSelectFrame();
437 pSh
->LeaveSelFrameMode();
438 pSh
->SetTextFormatColl( pAddr
);
439 InsertLabEnvText(*pSh
, aFieldMgr
, rItem
.m_aAddrText
);
441 // Move Flys to the "old" pages
442 if (!aFlyArr
.empty())
443 pSh
->SetPageObjsNewPage(aFlyArr
);
446 pSh
->SttEndDoc(true);
450 if (nMode
== ENV_NEWDOC
)
453 pSh
->EndUndo(SwUndoId::UI_INSERT_ENVELOPE
);
455 if (nMode
== ENV_NEWDOC
)
457 pFrame
->GetFrame().Appear();
459 if ( rItem
.m_aAddrText
.indexOf('<') >= 0 )
461 static sal_uInt16
const aInva
[] =
468 pFrame
->GetBindings().Invalidate( aInva
);
470 // Open database beamer
471 ShowDBObj(*pNewView
, pSh
->GetDBData());
477 rReq
.AppendItem( rItem
);
478 if ( nMode
== ENV_NEWDOC
)
479 rReq
.AppendItem( SfxBoolItem( FN_PARAM_1
, true ) );
491 // Set pointer to top view
493 SetView(&pOldSh
->GetView());
497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */