Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / app / appenv.cxx
blob6c744867ada1e0d080fb9707d6113d1bee550c21
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
35 #include <swwait.hxx>
36 #include <swmodule.hxx>
37 #include <wrtsh.hxx>
38 #include <view.hxx>
39 #include <docsh.hxx>
40 #include <frmatr.hxx>
41 #include <fldbas.hxx>
42 #include <swundo.hxx>
43 #include <IDocumentDeviceAccess.hxx>
44 #include <dialoghelp.hxx>
45 #include <fmtcol.hxx>
46 #include <frmmgr.hxx>
47 #include <fldmgr.hxx>
48 #include <pagedesc.hxx>
49 #include <poolfmt.hxx>
50 #include <expfld.hxx>
51 #include <SwStyleNameMapper.hxx>
52 #include <fmtpdsc.hxx>
54 #include <cmdid.h>
55 #include <strings.hrc>
56 #include <swabstdlg.hxx>
57 #include <envimg.hxx>
58 #include "appenv.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 )
66 OUString sRet;
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() )
75 OUString sTmpText;
76 bool bField = false;
78 sal_Int32 nPos = aLine.indexOf( '<' );
79 if (0 != nPos)
81 sal_Int32 const nCopy((nPos != -1) ? nPos : aLine.getLength());
82 sTmpText = aLine.copy(0, nCopy);
83 aLine = aLine.copy(nCopy);
85 else
87 nPos = aLine.indexOf( '>' );
88 if ( nPos == -1 )
90 sTmpText = aLine;
91 aLine.clear();
93 else
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 );
105 sRet = sDBName;
106 bField = true;
110 if ( !bField )
111 rSh.Insert( sTmpText );
113 rSh.SplitNode();
115 rSh.DelLeft(); // Again remove last linebreak
117 return sRet;
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;
137 SwView *pNewView;
138 SwWrtShell *pOldSh,
139 *pSh;
141 // Get current shell
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 ) );
147 xDocSh->DoInitNew();
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();
153 if (!pSh)
154 return;
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
160 // a new document
161 if ( pOldSh )
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 );
177 if(pOldSh )
179 const SwPageDesc& rCurPageDesc = pOldSh->GetPageDesc(pOldSh->GetCurPageDesc());
180 OUString sEnvelope;
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);
200 if ( !pItem )
202 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
203 pDlg.disposeAndReset(pFact->CreateSwEnvDlg(GetFrameWeld(pMyDocSh), aSet, pOldSh, pTempPrinter, !bEnvChange));
204 nMode = pDlg->Execute();
206 else
208 const SfxBoolItem* pBoolItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
209 if ( pBoolItem && pBoolItem->GetValue() )
210 nMode = ENV_NEWDOC;
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;
220 aEnvCfg.Commit();
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
225 // dialog.
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
247 xDocSh->DoClose();
248 pSh = pOldSh;
249 //#i4251# selected text or objects in the document should
250 //not be deleted on inserting envelopes
251 pSh->EnterStdMode();
252 // Here it goes (insert)
253 pSh->StartUndo(SwUndoId::UI_INSERT_ENVELOPE);
254 pSh->StartAllAction();
255 pSh->SttEndDoc(true);
257 if (bEnvChange)
259 // followup template: page 2
260 pFollow = pSh->GetPageDesc(pSh->GetCurPageDesc()).GetFollow();
262 // Delete text from the first page
263 if ( !pSh->SttNxtPg(true) )
264 pSh->EndPg(true);
265 pSh->DelRight();
266 // Delete frame of the first page
267 if ( pSh->GotoFly(sSendMark) )
269 pSh->EnterSelFrameMode();
270 pSh->DelRight();
272 if ( pSh->GotoFly(sAddrMark) )
274 pSh->EnterSelFrameMode();
275 pSh->DelRight();
277 pSh->SttEndDoc(true);
279 else
280 // Followup template: page 1
281 pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
283 // Insert page break
284 if ( pSh->IsCursorInTable() )
286 pSh->SplitNode();
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 );
292 else
294 OUString sFollowName(pFollow->GetName());
295 pSh->InsertPageBreak(&sFollowName, std::nullopt);
297 pSh->SttEndDoc(true);
299 else
301 pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
302 // Let's go (print)
303 pSh->StartAllAction();
304 pSh->DoUndo(false);
306 // Again, copy the new collections "Sender" and "Receiver" to
307 // a new document
308 if ( pOldSh )
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() )
335 Swap( aPaperSize );
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;
347 break;
348 case ENV_HOR_RGHT: lLeft += std::max(tools::Long(0), aPaperSize.Width() - nPageW);
349 break;
350 case ENV_VER_LEFT: lUpper += std::max(tools::Long(0), aPaperSize.Width() - nPageH);
351 break;
352 case ENV_VER_CNTR: lUpper += std::max(tools::Long(0), aPaperSize.Width() - nPageH) / 2;
353 break;
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);
365 // Header and footer
366 rFormat.SetFormatAttr(SwFormatHeader(false));
367 pDesc->ChgHeaderShare(false);
368 rFormat.SetFormatAttr(SwFormatFooter(false));
369 pDesc->ChgFooterShare(false);
371 // Page numbering
372 pDesc->SetUseOn(UseOnPage::All);
374 // Page size
375 rFormat.SetFormatAttr(SwFormatFrameSize(SwFrameSize::Fixed,
376 nPageW + lLeft, nPageH + lUpper));
378 // Set type of page numbering
379 SvxNumberType aType;
380 aType.SetNumberingType(SVX_NUM_NUMBER_NONE);
381 pDesc->SetNumType(aType);
383 // Followup template
384 if (pFollow)
385 pDesc->SetFollow(pFollow);
387 // Landscape
388 pDesc->SetLandscape( rItem.m_eAlign >= ENV_VER_LEFT &&
389 rItem.m_eAlign <= ENV_VER_RGHT);
391 // Apply page description
393 size_t nPos;
394 pSh->FindPageDescByName( pDesc->GetName(),
395 false,
396 &nPos );
398 pSh->ChgPageDesc( nPos, *pDesc);
399 pSh->ChgCurPageDesc(*pDesc);
401 // Insert Frame
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 );
411 // Sender
412 if (rItem.m_bSend)
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();
428 // Addressee
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);
445 // Finished
446 pSh->SttEndDoc(true);
448 pSh->EndAllAction();
450 if (nMode == ENV_NEWDOC)
451 pSh->DoUndo();
452 else
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[] =
463 SID_SBA_BRW_UPDATE,
464 SID_SBA_BRW_INSERT,
465 SID_SBA_BRW_MERGE,
468 pFrame->GetBindings().Invalidate( aInva );
470 // Open database beamer
471 ShowDBObj(*pNewView, pSh->GetDBData());
475 if ( !pItem )
477 rReq.AppendItem( rItem );
478 if ( nMode == ENV_NEWDOC )
479 rReq.AppendItem( SfxBoolItem( FN_PARAM_1, true ) );
482 rReq.Done();
484 else // Abort
486 rReq.Ignore();
488 xDocSh->DoClose();
489 --nTitleNo;
491 // Set pointer to top view
492 if (pOldSh)
493 SetView(&pOldSh->GetView());
497 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */