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