xref: /trunk/main/sw/source/ui/app/appenv.cxx (revision efeef26f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #if STLPORT_VERSION>=321
29 #include <cstdarg>
30 #endif
31 
32 
33 #include <hintids.hxx>
34 
35 #include <sfx2/request.hxx>
36 #include <svx/svxids.hrc>
37 
38 #include <svtools/svmedit.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/wrkwin.hxx>
41 #include <sfx2/app.hxx>
42 #include <sfx2/docfac.hxx>
43 #include <sfx2/printer.hxx>
44 #include <vcl/msgbox.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include <editeng/boxitem.hxx>
47 #include <editeng/lrspitem.hxx>
48 #include <editeng/ulspitem.hxx>
49 #include <editeng/pbinitem.hxx>
50 #include <editeng/paperinf.hxx>
51 #include <editeng/brkitem.hxx>
52 #include <fmthdft.hxx>
53 #include <swwait.hxx>
54 #include <paratr.hxx>
55 #include <swmodule.hxx>
56 #include <wrtsh.hxx>
57 #include <view.hxx>
58 #include <docsh.hxx>
59 #include <frmatr.hxx>
60 #include <fldbas.hxx>
61 #include <swundo.hxx>
62 #include <IDocumentDeviceAccess.hxx>
63 #include <dbmgr.hxx>
64 #include <fmtcol.hxx>
65 #include <frmmgr.hxx>
66 #include <fldmgr.hxx>
67 #include <pagedesc.hxx>
68 #include <poolfmt.hxx>
69 #include <expfld.hxx>
70 #include <SwStyleNameMapper.hxx>
71 #include <crsskip.hxx>
72 
73 #include <cmdid.h>
74 #ifndef _GLOBALS_HRC
75 #include <globals.hrc>
76 #endif
77 #ifndef _APP_HRC
78 #include <app.hrc>
79 #endif
80 #ifndef _POOLFMT_HRC
81 #include <poolfmt.hrc>
82 #endif
83 #include "swabstdlg.hxx"
84 #include "envelp.hrc"
85 #include "envimg.hxx"
86 
87 #define ENV_NEWDOC		RET_OK
88 #define ENV_INSERT		RET_USER
89 #define ENV_CANCEL		SHRT_MAX
90 
91 
92 // --------------------------------------------------------------------------
93 
94 
95 // Funktion wird fuer Etiketten und Briefumschlaege benutzt!
96 //	im applab.cxx und appenv.cxx
97 String InsertLabEnvText( SwWrtShell& rSh, SwFldMgr& rFldMgr, const String& rText )
98 {
99 	String sRet;
100 	String aText(rText);
101 	aText.EraseAllChars( '\r' );
102 
103 
104 	sal_uInt16 nTokenPos = 0;
105 	while( STRING_NOTFOUND != nTokenPos )
106 	{
107 		String aLine = aText.GetToken( 0, '\n', nTokenPos );
108 		while ( aLine.Len() )
109 		{
110 			String sTmpText;
111 			sal_Bool bField = sal_False;
112 
113 			sal_uInt16 nPos = aLine.Search( '<' );
114 			if ( nPos )
115 			{
116 				sTmpText = aLine.Copy( 0, nPos );
117 				aLine.Erase( 0, nPos );
118 //				sTmpText = aLine.Cut( 0, nPos );
119 			}
120 			else
121 			{
122 				nPos = aLine.Search( '>' );
123 				if ( nPos == STRING_NOTFOUND )
124 				{
125 					sTmpText = aLine;
126 					aLine.Erase();
127 //					sTmpText = aLine.Cut();
128 				}
129 				else
130 				{
131 					sTmpText = aLine.Copy( 0, nPos + 1);
132 					aLine.Erase( 0, nPos + 1);
133 //					sTmpText = aLine.Cut( 0, nPos + 1 );
134 
135 					// Datenbankfelder muesen mind. 3 Punkte beinhalten!
136 					String sDBName( sTmpText.Copy( 1, sTmpText.Len() - 2));
137 					sal_uInt16 nCnt = sDBName.GetTokenCount('.');
138 					if (nCnt >= 3)
139 					{
140                         ::ReplacePoint(sDBName, sal_True);
141                         SwInsertFld_Data aData(TYP_DBFLD, 0, sDBName, aEmptyStr, 0, &rSh );
142                         rFldMgr.InsertFld( aData );
143 						sRet = sDBName;
144 						bField = sal_True;
145 					}
146 				}
147 			}
148 			if ( !bField )
149 				rSh.Insert( sTmpText );
150 		}
151 		rSh.InsertLineBreak();
152 	}
153 	rSh.DelLeft();	// Letzten Linebreak wieder l???schen
154 
155 	return sRet;
156 }
157 
158 // ----------------------------------------------------------------------------
159 
160 
161 void lcl_CopyCollAttr(SwWrtShell* pOldSh, SwWrtShell* pNewSh, sal_uInt16 nCollId)
162 {
163 	sal_uInt16 nCollCnt = pOldSh->GetTxtFmtCollCount();
164 	SwTxtFmtColl* pColl;
165 	for( sal_uInt16 nCnt = 0; nCnt < nCollCnt; ++nCnt )
166 		if(nCollId == (pColl = &pOldSh->GetTxtFmtColl(nCnt))->GetPoolFmtId())
167             pNewSh->GetTxtCollFromPool(nCollId)->SetFmtAttr(pColl->GetAttrSet());
168 }
169 
170 // ----------------------------------------------------------------------------
171 
172 
173 void SwModule::InsertEnv( SfxRequest& rReq )
174 {
175 static sal_uInt16 nTitleNo = 0;
176 
177 	SwDocShell		*pMyDocSh;
178 	SfxViewFrame	*pFrame;
179     SwView          *pNewView;
180 	SwWrtShell		*pOldSh,
181 					*pSh;
182 
183 	//aktuelle Shell besorgen
184 	pMyDocSh = (SwDocShell*) SfxObjectShell::Current();
185 	pOldSh	 = pMyDocSh ? pMyDocSh->GetWrtShell() : 0;
186 
187 	// Neues Dokument erzeugen (kein Show!)
188 	SfxObjectShellLock xDocSh( new SwDocShell( SFX_CREATE_MODE_STANDARD ) );
189 	xDocSh->DoInitNew( 0 );
190     pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, 0 );
191     pNewView = (SwView*) pFrame->GetViewShell();
192     pNewView->AttrChangedNotify( &pNewView->GetWrtShell() );//Damit SelectShell gerufen wird.
193     pSh = pNewView->GetWrtShellPtr();
194 
195 	String aTmp( SW_RES(STR_ENV_TITLE) );
196 	aTmp += String::CreateFromInt32( ++nTitleNo );
197 	xDocSh->SetTitle( aTmp );
198 
199 	// Ggf. alte Collections "Absender" und "Empfaenger" in neues
200 	// Dokument kopieren
201 	if ( pOldSh )
202 	{
203 		::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_JAKETADRESS);
204 		::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS);
205 	}
206 
207 	// SwEnvItem aus Config lesen
208 	SwEnvCfgItem aEnvCfg;
209 
210 	//Haben wir schon einen Briefumschlag.
211 	sal_Bool bEnvChange = sal_False;
212 
213 	SfxItemSet aSet(GetPool(), FN_ENVELOP, FN_ENVELOP, 0);
214 	aSet.Put(aEnvCfg.GetItem());
215 
216     SfxPrinter* pTempPrinter = pSh->getIDocumentDeviceAccess()->getPrinter( true );
217 	if(pOldSh )
218 	{
219 		const SwPageDesc& rCurPageDesc = pOldSh->GetPageDesc(pOldSh->GetCurPageDesc());
220 		String sJacket;
221 		SwStyleNameMapper::FillUIName( RES_POOLPAGE_JAKET, sJacket );
222 		bEnvChange = rCurPageDesc.GetName() == sJacket;
223 
224         IDocumentDeviceAccess* pIDDA_old = pOldSh->getIDocumentDeviceAccess();
225         if( pIDDA_old->getPrinter( false ) )
226 		{
227             IDocumentDeviceAccess* pIDDA = pSh->getIDocumentDeviceAccess();
228             pIDDA->setJobsetup( *pIDDA_old->getJobsetup() );
229 			//#69563# if it isn't the same printer then the pointer has been invalidated!
230             pTempPrinter = pIDDA->getPrinter( true );
231 		}
232 		pTempPrinter->SetPaperBin(rCurPageDesc.GetMaster().GetPaperBin().GetValue());
233 
234 	}
235 
236 	Window *pParent = pOldSh ? pOldSh->GetWin() : 0;
237 	SfxAbstractTabDialog * pDlg=NULL;
238     short nMode = ENV_INSERT;
239 
240     SFX_REQUEST_ARG( rReq, pItem, SwEnvItem, FN_ENVELOP, sal_False );
241     if ( !pItem )
242     {
243         SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
244         DBG_ASSERT(pFact, "SwAbstractDialogFactory fail!");
245 
246         pDlg = pFact->CreateSwEnvDlg( pParent, aSet, pOldSh, pTempPrinter, !bEnvChange, DLG_ENV );
247         DBG_ASSERT(pDlg, "Dialogdiet fail!");
248         nMode = pDlg->Execute();
249     }
250     else
251     {
252         SFX_REQUEST_ARG( rReq, pBoolItem, SfxBoolItem, FN_PARAM_1, sal_False );
253         if ( pBoolItem && pBoolItem->GetValue() )
254             nMode = ENV_NEWDOC;
255     }
256 
257 	if (nMode == ENV_NEWDOC || nMode == ENV_INSERT)
258 	{
259 		SwWait aWait( (SwDocShell&)*xDocSh, sal_True );
260 
261 		// Dialog auslesen, Item in Config speichern
262         const SwEnvItem& rItem = pItem ? *pItem : (const SwEnvItem&) pDlg->GetOutputItemSet()->Get(FN_ENVELOP);
263 		aEnvCfg.GetItem() = rItem;
264 		aEnvCfg.Commit();
265 
266 		//Wenn wir Drucken uebernehmen wir den eingestellten Jobsetup aus
267 		//dem Dialog. Die Informationen muessen hier vor dem evtl. zerstoeren
268 		//der neuen Shell gesetzt werden, weil deren Drucker an den Dialog
269 		//gereicht wurde.
270 		if ( nMode != ENV_NEWDOC )
271 		{
272 			ASSERT(pOldSh, "Kein Dokument - war 'Einfuegen' nicht disabled???");
273             SvxPaperBinItem aItem( RES_PAPER_BIN );
274             aItem.SetValue((sal_uInt8)pSh->getIDocumentDeviceAccess()->getPrinter(true)->GetPaperBin());
275             pOldSh->GetPageDescFromPool(RES_POOLPAGE_JAKET)->GetMaster().SetFmtAttr(aItem);
276 		}
277 
278 		SwWrtShell *pTmp = nMode == ENV_INSERT ? pOldSh : pSh;
279 		const SwPageDesc* pFollow = 0;
280 		SwTxtFmtColl *pSend = pTmp->GetTxtCollFromPool( RES_POOLCOLL_SENDADRESS ),
281 					 *pAddr = pTmp->GetTxtCollFromPool( RES_POOLCOLL_JAKETADRESS);
282 		const String &rSendMark = pSend->GetName();
283 		const String &rAddrMark = pAddr->GetName();
284 
285 		if (nMode == ENV_INSERT)
286 		{
287 
288 			SetView(&pOldSh->GetView()); // Pointer auf oberste View restaurieren
289 
290 			//Neues Dok wieder loeschen
291 			xDocSh->DoClose();
292 			pSh = pOldSh;
293             //#i4251# selected text or objects in the document should
294             //not be deleted on inserting envelopes
295             pSh->EnterStdMode();
296 			// Los geht's (Einfuegen)
297             pSh->StartUndo(UNDO_UI_INSERT_ENVELOPE, NULL);
298 			pSh->StartAllAction();
299 			pSh->SttEndDoc(sal_True);
300 
301 			if (bEnvChange)
302 			{
303 				// Folgevorlage: Seite 2
304 				pFollow = pSh->GetPageDesc(pSh->GetCurPageDesc()).GetFollow();
305 
306 				// Text der ersten Seite loeschen
307 				if ( !pSh->SttNxtPg(sal_True) )
308 					pSh->EndPg(sal_True);
309 				pSh->DelRight();
310 				// Rahmen der ersten Seite loeschen
311 				if( pSh->GotoFly( rSendMark ) )
312 				{
313 					pSh->EnterSelFrmMode();
314 					pSh->DelRight();
315 				}
316 				if ( pSh->GotoFly( rAddrMark ) )
317 				{
318 					pSh->EnterSelFrmMode();
319 					pSh->DelRight();
320 				}
321 				pSh->SttEndDoc(sal_True);
322 			}
323 			else
324 				// Folgevorlage: Seite 1
325 				pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
326 
327 			// Seitenumbruch einfuegen
328 			if ( pSh->IsCrsrInTbl() )
329 			{
330 				pSh->SplitNode();
331 				pSh->Right( CRSR_SKIP_CHARS, sal_False, 1, sal_False );
332                 SfxItemSet aBreakSet( pSh->GetAttrPool(), RES_BREAK, RES_BREAK, 0 );
333                 aBreakSet.Put( SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) );
334                 pSh->SetTblAttr( aBreakSet );
335 			}
336 			else
337 				pSh->InsertPageBreak(0, sal_False);
338 			pSh->SttEndDoc(sal_True);
339 		}
340 		else
341 		{
342 			pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc());
343 			// Los geht's (Drucken)
344 			pSh->StartAllAction();
345 			pSh->DoUndo(sal_False);
346 
347 			// Neue Collections "Absender" und "Empfaenger" wieder in neues
348 			// Dokument kopieren
349 			if ( pOldSh )
350 			{
351 				::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_JAKETADRESS);
352 				::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS);
353 			}
354 		}
355 
356 		SET_CURR_SHELL(pSh);
357 		pSh->SetNewDoc();		// Performanceprobleme vermeiden
358 
359 		// Flys dieser Seite merken
360 		SvPtrarr aFlyArr(0, 5);
361 		if( ENV_NEWDOC != nMode && !bEnvChange )
362 			pSh->GetPageObjs( aFlyArr );
363 
364 		// Page-Desc ermitteln
365 		SwPageDesc* pDesc = pSh->GetPageDescFromPool(RES_POOLPAGE_JAKET);
366 		SwFrmFmt&   rFmt  = pDesc->GetMaster();
367 
368         Printer *pPrt = pSh->getIDocumentDeviceAccess()->getPrinter( true );
369 
370 		// Raender (setzen sich zusammen aus Shift-Offset und
371 		// Ausrichtung)
372 		Size aPaperSize = pPrt->PixelToLogic( pPrt->GetPaperSizePixel(),
373 											  MAP_TWIP);
374 		if ( !aPaperSize.Width() && !aPaperSize.Height() )
375             		aPaperSize = SvxPaperInfo::GetPaperSize(PAPER_A4);
376 		if ( aPaperSize.Width() > aPaperSize.Height() )
377 			Swap( aPaperSize );
378 
379 		long lLeft  = rItem.lShiftRight,
380 			 lUpper = rItem.lShiftDown;
381 
382 		sal_uInt16 nPageW = (sal_uInt16) Max(rItem.lWidth, rItem.lHeight),
383 			   nPageH = (sal_uInt16) Min(rItem.lWidth, rItem.lHeight);
384 
385 		switch (rItem.eAlign)
386 		{
387 			case ENV_HOR_LEFT: break;
388 			case ENV_HOR_CNTR: lLeft  += Max(0L, long(aPaperSize.Width() - nPageW)) / 2;
389 							   break;
390 			case ENV_HOR_RGHT: lLeft  += Max(0L, long(aPaperSize.Width() - nPageW));
391 							   break;
392 			case ENV_VER_LEFT: lUpper += Max(0L, long(aPaperSize.Width() - nPageH));
393 							   break;
394 			case ENV_VER_CNTR: lUpper += Max(0L, long(aPaperSize.Width() - nPageH)) / 2;
395 							   break;
396 			case ENV_VER_RGHT: break;
397 		}
398         SvxLRSpaceItem aLRMargin( RES_LR_SPACE );
399         SvxULSpaceItem aULMargin( RES_UL_SPACE );
400 		aLRMargin.SetLeft ((sal_uInt16) lLeft );
401 		aULMargin.SetUpper((sal_uInt16) lUpper);
402 		aLRMargin.SetRight(0);
403 		aULMargin.SetLower(0);
404         rFmt.SetFmtAttr(aLRMargin);
405         rFmt.SetFmtAttr(aULMargin);
406 
407 		// Kopf-, Fusszeilen
408         rFmt.SetFmtAttr(SwFmtHeader(sal_Bool(sal_False)));
409 		pDesc->ChgHeaderShare(sal_False);
410         rFmt.SetFmtAttr(SwFmtFooter(sal_Bool(sal_False)));
411 		pDesc->ChgFooterShare(sal_False);
412 
413 		// Seitennumerierung
414 		pDesc->SetUseOn(nsUseOnPage::PD_ALL);
415 
416 		// Einstellen der Seitengroesse
417         rFmt.SetFmtAttr(SwFmtFrmSize(ATT_FIX_SIZE,
418 											nPageW + lLeft, nPageH + lUpper));
419 
420 		// Einstellen der Numerierungsart der Seite
421 		SvxNumberType aType;
422 		aType.SetNumberingType(SVX_NUM_NUMBER_NONE);
423 		pDesc->SetNumType(aType);
424 
425 		// Folgevorlage
426 		if (pFollow)
427 			pDesc->SetFollow(pFollow);
428 
429 		// Landscape
430 		pDesc->SetLandscape( rItem.eAlign >= ENV_VER_LEFT &&
431 							 rItem.eAlign <= ENV_VER_RGHT);
432 
433 		// Page-Desc anwenden
434 
435 		sal_uInt16 nPos;
436 		pSh->FindPageDescByName( pDesc->GetName(),
437 									sal_False,
438 									&nPos );
439 
440 
441 		pSh->ChgPageDesc( nPos, *pDesc);
442 		pSh->ChgCurPageDesc(*pDesc);
443 
444 		// Rahmen einfuegen
445 		SwFlyFrmAttrMgr aMgr(sal_False, pSh, FRMMGR_TYPE_ENVELP);
446 		SwFldMgr aFldMgr;
447         aMgr.SetHeightSizeType(ATT_VAR_SIZE);
448 
449         //Defaults ueberschreiben!
450         aMgr.GetAttrSet().Put( SvxBoxItem(RES_BOX) );
451         aMgr.SetULSpace( 0L, 0L );
452         aMgr.SetLRSpace( 0L, 0L );
453 
454 		// Absender
455 		if (rItem.bSend)
456 		{
457 			pSh->SttEndDoc(sal_True);
458             aMgr.InsertFlyFrm(FLY_AT_PAGE,
459 				Point(rItem.lSendFromLeft + lLeft, rItem.lSendFromTop  + lUpper),
460 				Size (rItem.lAddrFromLeft - rItem.lSendFromLeft, 0));
461 
462 			pSh->EnterSelFrmMode();
463 			pSh->SetFlyName( rSendMark );
464 			pSh->UnSelectFrm();
465 			pSh->LeaveSelFrmMode();
466 			pSh->SetTxtFmtColl( pSend );
467 			InsertLabEnvText( *pSh, aFldMgr, rItem.aSendText );
468 			aMgr.UpdateAttrMgr();
469 		}
470 
471 		// Empfaenger
472 		pSh->SttEndDoc(sal_True);
473 
474         aMgr.InsertFlyFrm(FLY_AT_PAGE,
475 			Point(rItem.lAddrFromLeft + lLeft, rItem.lAddrFromTop  + lUpper),
476 			Size (nPageW - rItem.lAddrFromLeft - 566, 0));
477 		pSh->EnterSelFrmMode();
478 		pSh->SetFlyName( rAddrMark );
479 		pSh->UnSelectFrm();
480 		pSh->LeaveSelFrmMode();
481 		pSh->SetTxtFmtColl( pAddr );
482 		InsertLabEnvText(*pSh, aFldMgr, rItem.aAddrText);
483 
484 		// Flys auf die "alten" Seiten verschieben
485 		if (aFlyArr.Count())
486 			pSh->SetPageObjsNewPage(aFlyArr, 1);
487 
488 		// Fertig
489 		pSh->SttEndDoc(sal_True);
490 
491 		pSh->EndAllAction();
492 
493 		if (nMode == ENV_NEWDOC)
494 			pSh->DoUndo(sal_True);
495 		else
496             pSh->EndUndo(UNDO_UI_INSERT_ENVELOPE);
497 
498 		if (nMode == ENV_NEWDOC)
499 		{
500 			pFrame->GetFrame().Appear();
501 
502 			if ( rItem.aAddrText.indexOf('<') >= 0 )
503 			{
504 				static sal_uInt16 __READONLY_DATA aInva[] =
505 									{
506 										SID_SBA_BRW_UPDATE,
507 										SID_SBA_BRW_INSERT,
508 										SID_SBA_BRW_MERGE,
509 										0
510 									};
511 				pFrame->GetBindings().Invalidate( aInva );
512 
513 				// Datenbankbeamer oeffnen
514                 ShowDBObj(*pNewView, pSh->GetDBData());
515 			}
516 		}
517 
518         if ( !pItem )
519         {
520             rReq.AppendItem( rItem );
521             if ( nMode == ENV_NEWDOC )
522                 rReq.AppendItem( SfxBoolItem( FN_PARAM_1, sal_True ) );
523         }
524 
525         rReq.Done();
526 	}
527 	else	//Abbruch
528 	{
529         rReq.Ignore();
530 
531 		xDocSh->DoClose();
532 		--nTitleNo;
533 
534 		// Pointer auf oberste View restaurieren
535 		if (pOldSh)
536 			SetView(&pOldSh->GetView());
537 	}
538 	delete pDlg;
539 }
540 
541 
542