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