xref: /AOO41X/main/sw/source/ui/app/appenv.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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