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 <com/sun/star/text/HoriOrientation.hpp> 28 #include <com/sun/star/text/VertOrientation.hpp> 29 #include <com/sun/star/text/RelOrientation.hpp> 30 #include <svx/svxids.hrc> 31 #include "hintids.hxx" 32 #include <tools/string.hxx> 33 #include <svl/urihelper.hxx> 34 #include <vcl/svapp.hxx> 35 #include <vcl/wrkwin.hxx> 36 #include <svtools/htmlkywd.hxx> 37 #include <svtools/htmlout.hxx> 38 #include <svtools/imap.hxx> 39 #include <svtools/imapobj.hxx> 40 #include <svtools/htmlcfg.hxx> 41 #include <svx/xoutbmp.hxx> 42 #include <editeng/boxitem.hxx> 43 #include <editeng/lrspitem.hxx> 44 #include <editeng/ulspitem.hxx> 45 #include <editeng/brshitem.hxx> 46 47 48 #include <fmtanchr.hxx> 49 #include <fmtornt.hxx> 50 #include <fmturl.hxx> 51 #include <fmtfsize.hxx> 52 #include <fmtclds.hxx> 53 #include <fmtcntnt.hxx> 54 #include <fmtsrnd.hxx> 55 #include <fmtinfmt.hxx> 56 #include <txtinet.hxx> 57 #include "frmatr.hxx" 58 #include <grfatr.hxx> 59 #include <flypos.hxx> 60 #include <docary.hxx> 61 #include <ndgrf.hxx> 62 63 #include "doc.hxx" 64 #include "ndtxt.hxx" 65 #include "pam.hxx" 66 #include "swerror.h" 67 #include "frmfmt.hxx" 68 #include "wrthtml.hxx" 69 #include "css1kywd.hxx" 70 #include "htmlfly.hxx" 71 72 using namespace ::com::sun::star; 73 74 //////////////////////////////////////////////////////////// 75 76 const sal_uLong HTML_FRMOPTS_IMG_ALL = 77 HTML_FRMOPT_ALT | 78 HTML_FRMOPT_SIZE | 79 HTML_FRMOPT_ANYSIZE | 80 HTML_FRMOPT_BORDER | 81 HTML_FRMOPT_NAME; 82 const sal_uLong HTML_FRMOPTS_IMG_CNTNR = 83 HTML_FRMOPTS_IMG_ALL | 84 HTML_FRMOPT_ABSSIZE; 85 const sal_uLong HTML_FRMOPTS_IMG = 86 HTML_FRMOPTS_IMG_ALL | 87 HTML_FRMOPT_ALIGN | 88 HTML_FRMOPT_SPACE | 89 HTML_FRMOPT_BRCLEAR; 90 const sal_uLong HTML_FRMOPTS_IMG_CSS1 = 91 HTML_FRMOPT_S_ALIGN | 92 HTML_FRMOPT_S_SPACE; 93 94 const sal_uLong HTML_FRMOPTS_DIV = 95 HTML_FRMOPT_ID | 96 HTML_FRMOPT_S_ALIGN | 97 HTML_FRMOPT_S_SIZE | 98 HTML_FRMOPT_ANYSIZE | 99 HTML_FRMOPT_ABSSIZE | 100 HTML_FRMOPT_S_SPACE | 101 HTML_FRMOPT_S_BORDER | 102 HTML_FRMOPT_S_BACKGROUND | 103 HTML_FRMOPT_BRCLEAR | 104 HTML_FRMOPT_DIR; 105 106 const sal_uLong HTML_FRMOPTS_MULTICOL = 107 HTML_FRMOPT_ID | 108 HTML_FRMOPT_WIDTH | 109 HTML_FRMOPT_ANYSIZE | 110 HTML_FRMOPT_ABSSIZE | 111 HTML_FRMOPT_DIR; 112 const sal_uLong HTML_FRMOPTS_MULTICOL_CNTNR = 113 HTML_FRMOPTS_MULTICOL; 114 const sal_uLong HTML_FRMOPTS_MULTICOL_CSS1 = 115 HTML_FRMOPT_S_ALIGN | 116 HTML_FRMOPT_S_SIZE | 117 HTML_FRMOPT_S_SPACE | 118 HTML_FRMOPT_S_BORDER| 119 HTML_FRMOPT_S_BACKGROUND; 120 121 const sal_uLong HTML_FRMOPTS_SPACER = 122 HTML_FRMOPT_ALIGN | 123 HTML_FRMOPT_SIZE | 124 HTML_FRMOPT_ANYSIZE | 125 HTML_FRMOPT_BRCLEAR | 126 HTML_FRMOPT_MARGINSIZE | 127 HTML_FRMOPT_ABSSIZE; 128 129 const sal_uLong HTML_FRMOPTS_CNTNR = 130 HTML_FRMOPT_S_ALIGN | 131 HTML_FRMOPT_S_SPACE | 132 HTML_FRMOPT_S_WIDTH | 133 HTML_FRMOPT_ANYSIZE | 134 HTML_FRMOPT_ABSSIZE | 135 HTML_FRMOPT_S_PIXSIZE; 136 137 138 static Writer& OutHTML_FrmFmtTableNode( Writer& rWrt, const SwFrmFmt& rFrmFmt ); 139 static Writer& OutHTML_FrmFmtAsMulticol( Writer& rWrt, const SwFrmFmt& rFmt, 140 sal_Bool bInCntnr ); 141 static Writer& OutHTML_FrmFmtAsSpacer( Writer& rWrt, const SwFrmFmt& rFmt ); 142 static Writer& OutHTML_FrmFmtAsDivOrSpan( Writer& rWrt, 143 const SwFrmFmt& rFrmFmt, sal_Bool bSpan ); 144 static Writer& OutHTML_FrmFmtAsImage( Writer& rWrt, const SwFrmFmt& rFmt, 145 sal_Bool bInCntnr ); 146 147 static Writer& OutHTML_FrmFmtGrfNode( Writer& rWrt, const SwFrmFmt& rFmt, 148 sal_Bool bInCntnr ); 149 150 static Writer& OutHTML_FrmFmtAsMarquee( Writer& rWrt, const SwFrmFmt& rFrmFmt, 151 const SdrObject& rSdrObj ); 152 //----------------------------------------------------------------------- 153 154 extern HTMLOutEvent __FAR_DATA aAnchorEventTable[]; 155 156 static HTMLOutEvent __FAR_DATA aImageEventTable[] = 157 { 158 { OOO_STRING_SVTOOLS_HTML_O_SDonload, OOO_STRING_SVTOOLS_HTML_O_onload, SVX_EVENT_IMAGE_LOAD }, 159 { OOO_STRING_SVTOOLS_HTML_O_SDonabort, OOO_STRING_SVTOOLS_HTML_O_onabort, SVX_EVENT_IMAGE_ABORT }, 160 { OOO_STRING_SVTOOLS_HTML_O_SDonerror, OOO_STRING_SVTOOLS_HTML_O_onerror, SVX_EVENT_IMAGE_ERROR }, 161 { 0, 0, 0 } 162 }; 163 164 static HTMLOutEvent __FAR_DATA aIMapEventTable[] = 165 { 166 { OOO_STRING_SVTOOLS_HTML_O_SDonmouseover, OOO_STRING_SVTOOLS_HTML_O_onmouseover, SFX_EVENT_MOUSEOVER_OBJECT }, 167 { OOO_STRING_SVTOOLS_HTML_O_SDonmouseout, OOO_STRING_SVTOOLS_HTML_O_onmouseout, SFX_EVENT_MOUSEOUT_OBJECT }, 168 { 0, 0, 0 } 169 }; 170 171 172 173 SV_IMPL_OP_PTRARR_SORT( SwHTMLPosFlyFrms, SwHTMLPosFlyFrmPtr ) 174 175 sal_uInt16 SwHTMLWriter::GuessFrmType( const SwFrmFmt& rFrmFmt, 176 const SdrObject*& rpSdrObj ) 177 { 178 SwHTMLFrmType eType; 179 180 if( RES_DRAWFRMFMT == rFrmFmt.Which() ) 181 { 182 // Als Default irgendein Zeichen-Objekt 183 eType = HTML_FRMTYPE_DRAW; 184 185 const SdrObject *pObj = 186 SwHTMLWriter::GetMarqueeTextObj( (const SwDrawFrmFmt &)rFrmFmt ); 187 if( pObj ) 188 { 189 // Laufschrift 190 rpSdrObj = pObj; 191 eType = HTML_FRMTYPE_MARQUEE; 192 } 193 else 194 { 195 pObj = GetHTMLControl( (const SwDrawFrmFmt &)rFrmFmt ); 196 197 if( pObj ) 198 { 199 // Form-Control 200 rpSdrObj = pObj; 201 eType = HTML_FRMTYPE_CONTROL; 202 } 203 } 204 } 205 else 206 { 207 // Als Default ein Textrahmen 208 eType = HTML_FRMTYPE_TEXT; 209 210 const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt(); 211 sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex()+1; 212 const SwNode* pNd = pDoc->GetNodes()[ nStt ]; 213 214 if( pNd->IsGrfNode() ) 215 { 216 // Grafik - Node 217 eType = HTML_FRMTYPE_GRF; 218 } 219 else if( pNd->IsOLENode() ) 220 { 221 // Applet, Plugin, Floating-Frame 222 eType = (SwHTMLFrmType)GuessOLENodeFrmType( *pNd ); 223 } 224 else 225 { 226 sal_uLong nEnd = pDoc->GetNodes()[nStt-1]->EndOfSectionIndex(); 227 228 const SfxPoolItem* pItem; 229 const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet(); 230 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_COL, 231 sal_True, &pItem ) && 232 ((const SwFmtCol *)pItem)->GetNumCols() > 1 ) 233 { 234 // spaltiger Rahmen 235 eType = HTML_FRMTYPE_MULTICOL; 236 } 237 else if( pNd->IsTableNode() ) 238 { 239 const SwTableNode *pTblNd = pNd->GetTableNode(); 240 sal_uLong nTblEnd = pTblNd->EndOfSectionIndex(); 241 242 if( nTblEnd+1 == nEnd ) 243 { 244 // Tabelle 245 eType = HTML_FRMTYPE_TABLE; 246 } 247 else if( nTblEnd+2 == nEnd ) 248 { 249 // Tabelle mit Unterschrft 250 eType = HTML_FRMTYPE_TABLE_CAP; 251 } 252 } 253 else if( pNd->IsTxtNode() ) 254 { 255 const SwTxtNode *pTxtNd = pNd->GetTxtNode(); 256 257 sal_Bool bEmpty = sal_False; 258 if( nStt==nEnd-1 && !pTxtNd->Len() ) 259 { 260 // leerer Rahmen? Nur wenn kein Rahmen am 261 // Text- oder Start-Node verankert ist. 262 bEmpty = sal_True; 263 if( pHTMLPosFlyFrms ) 264 { 265 for( sal_uInt16 i=0; i<pHTMLPosFlyFrms->Count(); i++ ) 266 { 267 sal_uLong nIdx = (*pHTMLPosFlyFrms)[i] 268 ->GetNdIndex().GetIndex(); 269 bEmpty = (nIdx != nStt) && (nIdx != nStt-1); 270 if( !bEmpty || nIdx > nStt ) 271 break; 272 } 273 } 274 } 275 if( bEmpty ) 276 { 277 const SvxBrushItem& rBrush = rFrmFmt.GetBackground(); 278 /// OD 02.09.2002 #99657# 279 /// background is not empty, if it has a background graphic 280 /// or its background color is not "no fill"/"auto fill". 281 if( GPOS_NONE != rBrush.GetGraphicPos() || 282 rBrush.GetColor() != COL_TRANSPARENT ) 283 bEmpty = sal_False; 284 } 285 if( bEmpty ) 286 { 287 // leerer Rahmen 288 eType = HTML_FRMTYPE_EMPTY; 289 } 290 else if( pDoc->GetNodes()[nStt+1]->IsTableNode() ) 291 { 292 const SwTableNode *pTblNd = 293 pDoc->GetNodes()[nStt+1]->GetTableNode(); 294 if( pTblNd->EndOfSectionIndex()+1 == nEnd ) 295 { 296 // Tabelle mit Ueberschrift 297 eType = HTML_FRMTYPE_TABLE_CAP; 298 } 299 } 300 } 301 } 302 } 303 304 return static_cast< sal_uInt16 >(eType); 305 } 306 307 void SwHTMLWriter::CollectFlyFrms() 308 { 309 ASSERT( HTML_CFG_MAX+1 == MAX_BROWSERS, 310 "number of browser configurations has changed" ); 311 312 sal_uInt8 nSz = (sal_uInt8)Min( pDoc->GetSpzFrmFmts()->Count(), sal_uInt16(255) ); 313 SwPosFlyFrms aFlyPos(pDoc->GetAllFlyFmts(bWriteAll ? 0 : pCurPam, sal_True)); 314 315 for(SwPosFlyFrms::const_iterator aIter(aFlyPos.begin()); aIter != aFlyPos.end(); aIter++) 316 { 317 const SwFrmFmt& rFrmFmt = (*aIter)->GetFmt(); 318 const SdrObject *pSdrObj = 0; 319 const SwPosition *pAPos; 320 const SwCntntNode *pACNd; 321 SwHTMLFrmType eType = (SwHTMLFrmType)GuessFrmType( rFrmFmt, pSdrObj ); 322 323 sal_uInt8 nMode; 324 const SwFmtAnchor& rAnchor = rFrmFmt.GetAnchor(); 325 sal_Int16 eHoriRel = rFrmFmt.GetHoriOrient().GetRelationOrient(); 326 switch( rAnchor.GetAnchorId() ) 327 { 328 case FLY_AT_PAGE: 329 case FLY_AT_FLY: 330 nMode = aHTMLOutFrmPageFlyTable[eType][nExportMode]; 331 break; 332 333 case FLY_AT_PARA: 334 // Absatz-gebundene Rahmen werden nur dann vor den 335 // Absatz geschrieben, wenn der Absatz einen Abstand 336 // hat. 337 if( text::RelOrientation::FRAME == eHoriRel && 338 (pAPos = rAnchor.GetCntntAnchor()) != 0 && 339 (pACNd = pAPos->nNode.GetNode().GetCntntNode()) != 0 ) 340 { 341 const SvxLRSpaceItem& rLRItem = 342 (const SvxLRSpaceItem&)pACNd->GetAttr(RES_LR_SPACE); 343 if( rLRItem.GetTxtLeft() || rLRItem.GetRight() ) 344 { 345 nMode = aHTMLOutFrmParaFrameTable[eType][nExportMode]; 346 break; 347 } 348 } 349 nMode = aHTMLOutFrmParaPrtAreaTable[eType][nExportMode]; 350 break; 351 352 case FLY_AT_CHAR: 353 if( text::RelOrientation::FRAME == eHoriRel || text::RelOrientation::PRINT_AREA == eHoriRel ) 354 nMode = aHTMLOutFrmParaPrtAreaTable[eType][nExportMode]; 355 else 356 nMode = aHTMLOutFrmParaOtherTable[eType][nExportMode]; 357 break; 358 359 default: 360 nMode = aHTMLOutFrmParaPrtAreaTable[eType][nExportMode]; 361 break; 362 } 363 364 if( !pHTMLPosFlyFrms ) 365 pHTMLPosFlyFrms = new SwHTMLPosFlyFrms; 366 367 SwHTMLPosFlyFrm *pNew = new SwHTMLPosFlyFrm(**aIter, pSdrObj, nMode); 368 pHTMLPosFlyFrms->Insert( pNew ); 369 } 370 } 371 372 sal_Bool SwHTMLWriter::OutFlyFrm( sal_uLong nNdIdx, xub_StrLen nCntntIdx, sal_uInt8 nPos, 373 HTMLOutContext *pContext ) 374 { 375 sal_Bool bFlysLeft = sal_False; // Noch Flys an aktueller Node-Position da? 376 377 // OutFlyFrm kan rekursiv aufgerufen werden. Deshalb muss man 378 // manchmal wieder von vorne anfangen, nachdem ein Fly ausgegeben 379 // wurde. 380 sal_Bool bRestart = sal_True; 381 while( pHTMLPosFlyFrms && bRestart ) 382 { 383 bFlysLeft = bRestart = sal_False; 384 385 // suche nach dem Anfang der FlyFrames 386 sal_uInt16 i; 387 388 for( i = 0; i < pHTMLPosFlyFrms->Count() && 389 (*pHTMLPosFlyFrms)[i]->GetNdIndex().GetIndex() < nNdIdx; i++ ) 390 ; 391 for( ; !bRestart && i < pHTMLPosFlyFrms->Count() && 392 (*pHTMLPosFlyFrms)[i]->GetNdIndex().GetIndex() == nNdIdx; i++ ) 393 { 394 SwHTMLPosFlyFrm *pPosFly = (*pHTMLPosFlyFrms)[i]; 395 if( ( HTML_POS_ANY == nPos || 396 pPosFly->GetOutPos() == nPos ) && 397 pPosFly->GetCntntIndex() == nCntntIdx ) 398 { 399 // Erst entfernen ist wichtig, weil in tieferen 400 // Rekursionen evtl. weitere Eintraege oder das 401 // ganze Array geloscht werden koennte. 402 pHTMLPosFlyFrms->Remove( i, 1 ); 403 i--; 404 if( !pHTMLPosFlyFrms->Count() ) 405 { 406 delete pHTMLPosFlyFrms; 407 pHTMLPosFlyFrms = 0; 408 bRestart = sal_True; // nicht wirklich, nur raus 409 // aus der Schleife 410 } 411 412 if( pContext ) 413 { 414 HTMLOutFuncs::FlushToAscii(Strm(), *pContext ); 415 pContext = 0; // one time only 416 } 417 418 OutFrmFmt( pPosFly->GetOutMode(), pPosFly->GetFmt(), 419 pPosFly->GetSdrObject() ); 420 switch( pPosFly->GetOutFn() ) 421 { 422 case HTML_OUT_DIV: 423 case HTML_OUT_SPAN: 424 case HTML_OUT_MULTICOL: 425 case HTML_OUT_TBLNODE: 426 bRestart = sal_True; // Hier wird's evtl rekursiv 427 break; 428 } 429 delete pPosFly; 430 } 431 else 432 { 433 bFlysLeft = sal_True; 434 } 435 } 436 } 437 438 return bFlysLeft; 439 } 440 441 void SwHTMLWriter::OutFrmFmt( sal_uInt8 nMode, const SwFrmFmt& rFrmFmt, 442 const SdrObject *pSdrObject ) 443 { 444 sal_uInt8 nCntnrMode = SwHTMLPosFlyFrm::GetOutCntnr( nMode ); 445 sal_uInt8 nOutMode = SwHTMLPosFlyFrm::GetOutFn(nMode); 446 const sal_Char *pCntnrStr = 0; 447 if( HTML_CNTNR_NONE != nCntnrMode ) 448 { 449 450 if( bLFPossible && HTML_CNTNR_DIV == nCntnrMode ) 451 OutNewLine(); 452 453 ByteString sOut( '<' ); 454 pCntnrStr = (HTML_CNTNR_DIV == nCntnrMode) 455 ? OOO_STRING_SVTOOLS_HTML_division 456 : OOO_STRING_SVTOOLS_HTML_span; 457 sOut += pCntnrStr; 458 ((((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\"") 459 += sCSS1_class_abs_pos) += '\"'; 460 Strm() << sOut.GetBuffer(); 461 462 // Fuer Nicht-Zeichenobekte eine Breite ausgeben 463 sal_uLong nFrmFlags = HTML_FRMOPTS_CNTNR; 464 465 // Fuer spaltige Rahmen koennen wir auch noch den Hintergrund ausgeben. 466 if( HTML_OUT_MULTICOL == nOutMode ) 467 nFrmFlags |= HTML_FRMOPT_S_BACKGROUND|HTML_FRMOPT_S_BORDER; 468 469 if( IsHTMLMode( HTMLMODE_BORDER_NONE ) ) 470 nFrmFlags |= HTML_FRMOPT_S_NOBORDER; 471 OutCSS1_FrmFmtOptions( rFrmFmt, nFrmFlags, pSdrObject ); 472 Strm() << '>'; 473 474 if( HTML_CNTNR_DIV == nCntnrMode ) 475 { 476 IncIndentLevel(); 477 bLFPossible = sal_True; 478 } 479 } 480 481 switch( nOutMode ) 482 { 483 case HTML_OUT_TBLNODE: // OK 484 ASSERT( !pCntnrStr, "Table: Container ist hier nicht vorgesehen" ); 485 OutHTML_FrmFmtTableNode( *this, rFrmFmt ); 486 break; 487 case HTML_OUT_GRFNODE: // OK 488 OutHTML_FrmFmtGrfNode( *this, rFrmFmt, pCntnrStr != 0 ); 489 break; 490 case HTML_OUT_OLENODE: // OK 491 OutHTML_FrmFmtOLENode( *this, rFrmFmt, pCntnrStr != 0 ); 492 break; 493 case HTML_OUT_OLEGRF: // OK 494 OutHTML_FrmFmtOLENodeGrf( *this, rFrmFmt, pCntnrStr != 0 ); 495 break; 496 case HTML_OUT_DIV: 497 case HTML_OUT_SPAN: 498 ASSERT( !pCntnrStr, "Div: Container ist hier nicht vorgesehen" ); 499 OutHTML_FrmFmtAsDivOrSpan( *this, rFrmFmt, HTML_OUT_SPAN==nOutMode ); 500 break; 501 case HTML_OUT_MULTICOL: // OK 502 OutHTML_FrmFmtAsMulticol( *this, rFrmFmt, pCntnrStr != 0 ); 503 break; 504 case HTML_OUT_SPACER: // OK 505 ASSERT( !pCntnrStr, "Spacer: Container ist hier nicht vorgesehen" ); 506 OutHTML_FrmFmtAsSpacer( *this, rFrmFmt ); 507 break; 508 case HTML_OUT_CONTROL: // OK 509 OutHTML_DrawFrmFmtAsControl( *this, 510 (const SwDrawFrmFmt &)rFrmFmt, *pSdrObject, 511 pCntnrStr != 0 ); 512 break; 513 case HTML_OUT_AMARQUEE: 514 OutHTML_FrmFmtAsMarquee( *this, rFrmFmt, *pSdrObject ); 515 break; 516 case HTML_OUT_MARQUEE: 517 ASSERT( !pCntnrStr, "Marquee: Container ist hier nicht vorgesehen" ); 518 OutHTML_DrawFrmFmtAsMarquee( *this, 519 (const SwDrawFrmFmt &)rFrmFmt, *pSdrObject ); 520 break; 521 case HTML_OUT_GRFFRM: 522 OutHTML_FrmFmtAsImage( *this, rFrmFmt, pCntnrStr != 0 ); 523 break; 524 } 525 526 if( HTML_CNTNR_DIV == nCntnrMode ) 527 { 528 DecIndentLevel(); 529 if( bLFPossible ) 530 OutNewLine(); 531 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_division, sal_False ); 532 bLFPossible = sal_True; 533 } 534 else if( HTML_CNTNR_SPAN == nCntnrMode ) 535 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_span, sal_False ); 536 } 537 538 539 void SwHTMLWriter::OutFrmFmtOptions( const SwFrmFmt &rFrmFmt, 540 const String& rAlternateTxt, 541 ByteString &rEndTags, 542 sal_uInt32 nFrmOpts ) 543 { 544 ByteString sOut; 545 const SfxPoolItem* pItem; 546 const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet(); 547 548 // Name 549 if( (nFrmOpts & (HTML_FRMOPT_ID|HTML_FRMOPT_NAME)) && 550 rFrmFmt.GetName().Len() ) 551 { 552 const sal_Char *pStr = 553 (nFrmOpts & HTML_FRMOPT_ID) ? OOO_STRING_SVTOOLS_HTML_O_id : OOO_STRING_SVTOOLS_HTML_O_name; 554 ((sOut += ' ') += pStr) += "=\""; 555 Strm() << sOut.GetBuffer(); 556 HTMLOutFuncs::Out_String( Strm(), rFrmFmt.GetName(), eDestEnc, &aNonConvertableCharacters ); 557 sOut = '\"'; 558 } 559 560 // Name 561 if( nFrmOpts & HTML_FRMOPT_DIR ) 562 { 563 sal_uInt16 nDir = GetHTMLDirection( rItemSet ); 564 Strm() << sOut.GetBuffer(); 565 sOut.Erase(); 566 OutDirection( nDir ); 567 } 568 569 570 // ALT 571 if( (nFrmOpts & HTML_FRMOPT_ALT) && rAlternateTxt.Len() ) 572 { 573 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_alt) += "=\""; 574 Strm() << sOut.GetBuffer(); 575 HTMLOutFuncs::Out_String( Strm(), rAlternateTxt, eDestEnc, &aNonConvertableCharacters ); 576 sOut = '\"'; 577 } 578 579 // ALIGN 580 const sal_Char *pStr = 0; 581 RndStdIds eAnchorId = rFrmFmt.GetAnchor().GetAnchorId(); 582 if( (nFrmOpts & HTML_FRMOPT_ALIGN) && 583 ((FLY_AT_PARA == eAnchorId) || (FLY_AT_CHAR == eAnchorId)) ) 584 { 585 // MIB 12.3.98: Ist es nicht schlauer, absatzgebundene 586 // Rahmen notfalls links auszurichten als sie 587 // zeichengebunden einzufuegen??? 588 const SwFmtHoriOrient& rHoriOri = rFrmFmt.GetHoriOrient(); 589 if( !(nFrmOpts & HTML_FRMOPT_S_ALIGN) || 590 text::RelOrientation::FRAME == rHoriOri.GetRelationOrient() || 591 text::RelOrientation::PRINT_AREA == rHoriOri.GetRelationOrient() ) 592 { 593 pStr = text::HoriOrientation::RIGHT == rHoriOri.GetHoriOrient() 594 ? OOO_STRING_SVTOOLS_HTML_AL_right 595 : OOO_STRING_SVTOOLS_HTML_AL_left; 596 } 597 } 598 if( (nFrmOpts & HTML_FRMOPT_ALIGN) && !pStr && 599 ( (nFrmOpts & HTML_FRMOPT_S_ALIGN) == 0 || 600 (FLY_AS_CHAR == eAnchorId) ) && 601 SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_True, &pItem )) 602 { 603 switch( ((SwFmtVertOrient*)pItem)->GetVertOrient() ) 604 { 605 case text::VertOrientation::LINE_TOP: pStr = OOO_STRING_SVTOOLS_HTML_VA_top; break; 606 case text::VertOrientation::CHAR_TOP: 607 case text::VertOrientation::BOTTOM: pStr = OOO_STRING_SVTOOLS_HTML_VA_texttop; break; // geht nicht 608 case text::VertOrientation::LINE_CENTER: 609 case text::VertOrientation::CHAR_CENTER: pStr = OOO_STRING_SVTOOLS_HTML_VA_absmiddle; break; // geht nicht 610 case text::VertOrientation::CENTER: pStr = OOO_STRING_SVTOOLS_HTML_VA_middle; break; 611 case text::VertOrientation::LINE_BOTTOM: 612 case text::VertOrientation::CHAR_BOTTOM: pStr = OOO_STRING_SVTOOLS_HTML_VA_absbottom; break; // geht nicht 613 case text::VertOrientation::TOP: pStr = OOO_STRING_SVTOOLS_HTML_VA_bottom; break; 614 case text::VertOrientation::NONE: break; 615 } 616 } 617 if( pStr ) 618 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += pStr; 619 620 621 // HSPACE und VSPACE 622 Size aTwipSpc( 0, 0 ); 623 if( (nFrmOpts & (HTML_FRMOPT_SPACE|HTML_FRMOPT_MARGINSIZE)) && 624 SFX_ITEM_SET == rItemSet.GetItemState( RES_LR_SPACE, sal_True, &pItem )) 625 { 626 aTwipSpc.Width() = 627 ( ((SvxLRSpaceItem*)pItem)->GetLeft() + 628 ((SvxLRSpaceItem*)pItem)->GetRight() ) / 2; 629 nDfltLeftMargin = nDfltRightMargin = aTwipSpc.Width(); 630 } 631 if( (nFrmOpts & (HTML_FRMOPT_SPACE|HTML_FRMOPT_MARGINSIZE)) && 632 SFX_ITEM_SET == rItemSet.GetItemState( RES_UL_SPACE, sal_True, &pItem )) 633 { 634 aTwipSpc.Height() = 635 ( ((SvxULSpaceItem*)pItem)->GetUpper() + 636 ((SvxULSpaceItem*)pItem)->GetLower() ) / 2; 637 nDfltTopMargin = nDfltBottomMargin = (sal_uInt16)aTwipSpc.Height(); 638 } 639 640 if( (nFrmOpts & HTML_FRMOPT_SPACE) && 641 (aTwipSpc.Width() || aTwipSpc.Height()) && 642 Application::GetDefaultDevice() ) 643 { 644 Size aPixelSpc = 645 Application::GetDefaultDevice()->LogicToPixel( aTwipSpc, 646 MapMode(MAP_TWIP) ); 647 if( !aPixelSpc.Width() && aTwipSpc.Width() ) 648 aPixelSpc.Width() = 1; 649 if( !aPixelSpc.Height() && aTwipSpc.Height() ) 650 aPixelSpc.Height() = 1; 651 652 if( aPixelSpc.Width() ) 653 { 654 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_hspace) += '=') 655 += ByteString::CreateFromInt32( aPixelSpc.Width() ); 656 } 657 658 if( aPixelSpc.Height() ) 659 { 660 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_vspace) += '=') 661 += ByteString::CreateFromInt32( aPixelSpc.Height() ); 662 } 663 } 664 665 // Der Abstand muss bei der Groesse beruecksichtigt, wenn das entsprechende 666 // Flag gesetzt ist. 667 if( (nFrmOpts & HTML_FRMOPT_MARGINSIZE) ) 668 { 669 aTwipSpc.Width() *= -2; 670 aTwipSpc.Height() *= -2; 671 } 672 else 673 { 674 aTwipSpc.Width() = 0; 675 aTwipSpc.Height() = 0; 676 } 677 678 if( !(nFrmOpts & HTML_FRMOPT_ABSSIZE) && 679 SFX_ITEM_SET == rItemSet.GetItemState( RES_BOX, sal_True, &pItem )) 680 { 681 const SvxBoxItem* pBoxItem = (const SvxBoxItem*)pItem; 682 683 aTwipSpc.Width() += pBoxItem->CalcLineSpace( BOX_LINE_LEFT ); 684 aTwipSpc.Width() += pBoxItem->CalcLineSpace( BOX_LINE_RIGHT ); 685 aTwipSpc.Height() += pBoxItem->CalcLineSpace( BOX_LINE_TOP ); 686 aTwipSpc.Height() += pBoxItem->CalcLineSpace( BOX_LINE_BOTTOM ); 687 } 688 689 // WIDTH und/oder HEIGHT 690 // ATT_VAR_SIZE/ATT_MIN_SIZE nur ausgeben, wenn ANYSIZE gesezut ist 691 if( (nFrmOpts & HTML_FRMOPT_SIZE) && 692 SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ) && 693 ( (nFrmOpts & HTML_FRMOPT_ANYSIZE) || 694 ATT_FIX_SIZE == ((const SwFmtFrmSize *)pItem)->GetHeightSizeType()) ) 695 { 696 const SwFmtFrmSize *pFSItem = (const SwFmtFrmSize *)pItem; 697 sal_uInt8 nPrcWidth = pFSItem->GetWidthPercent(); 698 sal_uInt8 nPrcHeight = pFSItem->GetHeightPercent(); 699 700 // Groesse des Objekts Twips ohne Raender 701 Size aTwipSz( (nPrcWidth ? 0 702 : pFSItem->GetWidth()-aTwipSpc.Width()), 703 (nPrcHeight ? 0 704 : pFSItem->GetHeight()-aTwipSpc.Height()) ); 705 706 ASSERT( aTwipSz.Width() >= 0 && aTwipSz.Height() >= 0, 707 "Rahmengroesse minus Abstand < 0!!!???" ); 708 if( aTwipSz.Width() < 0 ) 709 aTwipSz.Width() = 0; 710 if( aTwipSz.Height() < 0 ) 711 aTwipSz.Height() = 0; 712 713 Size aPixelSz( 0, 0 ); 714 if( (aTwipSz.Width() || aTwipSz.Height()) && 715 Application::GetDefaultDevice() ) 716 { 717 aPixelSz = 718 Application::GetDefaultDevice()->LogicToPixel( aTwipSz, 719 MapMode(MAP_TWIP) ); 720 if( !aPixelSz.Width() && aTwipSz.Width() ) 721 aPixelSz.Width() = 1; 722 if( !aPixelSz.Height() && aTwipSz.Height() ) 723 aPixelSz.Height() = 1; 724 } 725 726 if( (nFrmOpts & HTML_FRMOPT_WIDTH) && 727 ((nPrcWidth && nPrcWidth!=255) || aPixelSz.Width()) ) 728 { 729 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width) += '='; 730 if( nPrcWidth ) 731 (sOut += ByteString::CreateFromInt32( nPrcWidth )) += '%'; 732 else 733 sOut += ByteString::CreateFromInt32( aPixelSz.Width() ); 734 } 735 736 if( (nFrmOpts & HTML_FRMOPT_HEIGHT) && 737 ((nPrcHeight && nPrcHeight!=255) || aPixelSz.Height()) ) 738 { 739 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_height) += '='; 740 if( nPrcHeight ) 741 (sOut += ByteString::CreateFromInt32( nPrcHeight )) += '%'; 742 else 743 sOut += ByteString::CreateFromInt32( aPixelSz.Height() ); 744 } 745 } 746 747 if( sOut.Len() ) 748 Strm() << sOut.GetBuffer(); 749 750 // Umlauf fuer absatzgeb. Grafiken als <BR CLEAR=...> in den String 751 // schreiben 752 if( (nFrmOpts & HTML_FRMOPT_BRCLEAR) && 753 ((FLY_AT_PARA == rFrmFmt.GetAnchor().GetAnchorId()) || 754 (FLY_AT_CHAR == rFrmFmt.GetAnchor().GetAnchorId())) && 755 SFX_ITEM_SET == rItemSet.GetItemState( RES_SURROUND, sal_True, &pItem )) 756 { 757 const SwFmtSurround* pSurround = (const SwFmtSurround*)pItem; 758 sal_Int16 eHoriOri = rFrmFmt.GetHoriOrient().GetHoriOrient(); 759 pStr = 0; 760 SwSurround eSurround = pSurround->GetSurround(); 761 sal_Bool bAnchorOnly = pSurround->IsAnchorOnly(); 762 switch( eHoriOri ) 763 { 764 case text::HoriOrientation::RIGHT: 765 { 766 switch( eSurround ) 767 { 768 case SURROUND_NONE: 769 case SURROUND_RIGHT: 770 pStr = OOO_STRING_SVTOOLS_HTML_AL_right; 771 break; 772 case SURROUND_LEFT: 773 case SURROUND_PARALLEL: 774 if( bAnchorOnly ) 775 bClearRight = sal_True; 776 break; 777 default: 778 ; 779 } 780 } 781 break; 782 783 default: 784 // #67508#: If a frame is centered, it gets left aligned. This 785 // should be taken into account here, too. 786 { 787 switch( eSurround ) 788 { 789 case SURROUND_NONE: 790 case SURROUND_LEFT: 791 pStr = OOO_STRING_SVTOOLS_HTML_AL_left; 792 break; 793 case SURROUND_RIGHT: 794 case SURROUND_PARALLEL: 795 if( bAnchorOnly ) 796 bClearLeft = sal_True; 797 break; 798 default: 799 ; 800 } 801 } 802 break; 803 804 } 805 806 if( pStr ) 807 { 808 (((((((sOut = '<') += OOO_STRING_SVTOOLS_HTML_linebreak) += ' ') 809 += OOO_STRING_SVTOOLS_HTML_O_clear) += '=') += pStr) += '>') += rEndTags; 810 rEndTags = sOut; 811 } 812 } 813 } 814 815 816 Writer& OutHTML_Image( Writer& rWrt, const SwFrmFmt &rFrmFmt, 817 const String &rGrfName, const String& rAlternateTxt, 818 const Size &rRealSize, sal_uInt32 nFrmOpts, 819 const sal_Char *pMarkType, 820 const ImageMap *pAltImgMap ) 821 { 822 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 823 824 // ggf. ein noch offenes Attribut voruebergehend beenden 825 if( rHTMLWrt.aINetFmts.Count() ) 826 { 827 SwFmtINetFmt *pINetFmt = 828 rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ]; 829 OutHTML_INetFmt( rWrt, *pINetFmt, sal_False ); 830 } 831 832 String aGrfNm( rGrfName ); 833 if( !HTMLOutFuncs::PrivateURLToInternalImg(aGrfNm) ) 834 aGrfNm = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(), aGrfNm); 835 836 const SfxPoolItem* pItem; 837 const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet(); 838 839 const SwFmtURL *pURLItem = 0; 840 841 // das URL-Attribut nur beruecksichtigen, wenn keine Image-Map 842 // uebergeben wurde 843 if( !pAltImgMap && 844 SFX_ITEM_SET == rItemSet.GetItemState( RES_URL, sal_True, &pItem )) 845 { 846 pURLItem = (const SwFmtURL *)pItem; 847 } 848 849 // Image-Map rausschreiben 850 const ImageMap *pIMap = pAltImgMap; 851 if( !pIMap && pURLItem ) 852 { 853 pIMap = pURLItem->GetMap(); 854 } 855 856 String aIMapName; 857 if( pIMap ) 858 { 859 // den Namen eindeutig machen 860 aIMapName = pIMap->GetName(); 861 String aNameBase; 862 if( aIMapName.Len() ) 863 aNameBase = aIMapName; 864 else 865 aNameBase.AssignAscii( OOO_STRING_SVTOOLS_HTML_map ); 866 if( !aIMapName.Len() ) 867 (aIMapName = aNameBase) 868 += String::CreateFromInt32( rHTMLWrt.nImgMapCnt ); 869 870 sal_Bool bFound; 871 do 872 { 873 bFound = sal_False; 874 for( sal_uInt16 i=0; i<rHTMLWrt.aImgMapNames.Count(); i++ ) 875 { 876 // TODO: Unicode: Comparison is case insensitive for ASCII 877 // characters only now! 878 if( aIMapName.EqualsIgnoreCaseAscii(*rHTMLWrt.aImgMapNames[i]) ) 879 { 880 bFound = sal_True; 881 break; 882 } 883 } 884 if( bFound ) 885 { 886 rHTMLWrt.nImgMapCnt++; 887 (aIMapName = aNameBase) 888 += String::CreateFromInt32( rHTMLWrt.nImgMapCnt ); 889 } 890 891 } while( bFound ); 892 893 sal_Bool bScale = sal_False; 894 //Size aGrfSize( rNode.GetTwipSize() ); 895 Fraction aScaleX( 1, 1 ); 896 Fraction aScaleY( 1, 1 ); 897 898 const SwFmtFrmSize& rFrmSize = rFrmFmt.GetFrmSize(); 899 const SvxBoxItem& rBox = rFrmFmt.GetBox(); 900 901 if( !rFrmSize.GetWidthPercent() && rRealSize.Width() ) 902 { 903 SwTwips nWidth = rFrmSize.GetWidth(); 904 nWidth -= ( rBox.CalcLineSpace(BOX_LINE_LEFT) + 905 rBox.CalcLineSpace(BOX_LINE_RIGHT) ); 906 907 ASSERT( nWidth>0, "Gibt es 0 twip breite Grafiken!?" ); 908 if( nWidth<=0 ) // sollte nicht passieren 909 nWidth = 1; 910 911 if( rRealSize.Width() != nWidth ) 912 { 913 aScaleX = Fraction( nWidth, rRealSize.Width() ); 914 bScale = sal_True; 915 } 916 } 917 if( !rFrmSize.GetHeightPercent() && rRealSize.Height() ) 918 { 919 SwTwips nHeight = rFrmSize.GetHeight(); 920 nHeight -= ( rBox.CalcLineSpace(BOX_LINE_TOP) + 921 rBox.CalcLineSpace(BOX_LINE_BOTTOM) ); 922 923 ASSERT( nHeight>0, "Gibt es 0 twip hohe Grafiken!?" ); 924 if( nHeight<=0 ) 925 nHeight = 1; 926 927 if( rRealSize.Height() != nHeight ) 928 { 929 aScaleY = Fraction( nHeight, rRealSize.Height() ); 930 bScale = sal_True; 931 } 932 } 933 934 rHTMLWrt.aImgMapNames.Insert( new String(aIMapName), 935 rHTMLWrt.aImgMapNames.Count() ); 936 937 ByteString aIndMap, aIndArea; 938 const sal_Char *pLF = 0, *pIndArea = 0, *pIndMap = 0; 939 #if defined(UNX) 940 sal_Char aLF[2] = "\x00"; 941 #endif 942 943 if( rHTMLWrt.bLFPossible ) 944 { 945 rHTMLWrt.OutNewLine( sal_True ); 946 rHTMLWrt.GetIndentString( aIndMap ); 947 rHTMLWrt.GetIndentString( aIndArea, 1 ); 948 #if defined(UNX) 949 aLF[0] = SwHTMLWriter::sNewLine; 950 pLF = aLF; 951 #else 952 pLF = SwHTMLWriter::sNewLine; 953 #endif 954 pIndArea = aIndArea.GetBuffer(); 955 pIndMap = aIndMap.GetBuffer(); 956 } 957 958 if( bScale ) 959 { 960 ImageMap aScaledIMap( *pIMap ); 961 aScaledIMap.Scale( aScaleX, aScaleY ); 962 HTMLOutFuncs::Out_ImageMap( rWrt.Strm(), rWrt.GetBaseURL(), aScaledIMap, aIMapName, 963 aIMapEventTable, 964 rHTMLWrt.bCfgStarBasic, 965 pLF, pIndArea, pIndMap, 966 rHTMLWrt.eDestEnc, 967 &rHTMLWrt.aNonConvertableCharacters ); 968 } 969 else 970 { 971 HTMLOutFuncs::Out_ImageMap( rWrt.Strm(), rWrt.GetBaseURL(), *pIMap, aIMapName, 972 aIMapEventTable, 973 rHTMLWrt.bCfgStarBasic, 974 pLF, pIndArea, pIndMap, 975 rHTMLWrt.eDestEnc, 976 &rHTMLWrt.aNonConvertableCharacters ); 977 } 978 } 979 980 // wenn meoglich vor der Grafik einen Zeilen-Umbruch ausgeben 981 if( rHTMLWrt.bLFPossible ) 982 rHTMLWrt.OutNewLine( sal_True ); 983 984 // Attribute die ausserhelb der Grafik geschreiben werden muessen sammeln 985 ByteString sOut; 986 ByteString aEndTags; 987 988 // implizite Sprungmarke -> <A NAME=...></A>...<IMG ...> 989 if( pMarkType && rFrmFmt.GetName().Len() ) 990 rHTMLWrt.OutImplicitMark( rFrmFmt.GetName(), pMarkType ); 991 992 // URL -> <A>...<IMG ... >...</A> 993 const SvxMacroItem *pMacItem = 0; 994 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRMMACRO, sal_True, &pItem )) 995 pMacItem = (const SvxMacroItem *)pItem; 996 997 if( pURLItem || pMacItem ) 998 { 999 String aMapURL; 1000 String aName; 1001 String aTarget; 1002 if( pURLItem ) 1003 { 1004 aMapURL = pURLItem->GetURL(); 1005 aName = pURLItem->GetName(); 1006 aTarget = pURLItem->GetTargetFrameName(); 1007 } 1008 sal_Bool bEvents = pMacItem && pMacItem->GetMacroTable().Count(); 1009 1010 if( aMapURL.Len() || aName.Len() || aTarget.Len() || bEvents ) 1011 { 1012 (sOut = '<') += OOO_STRING_SVTOOLS_HTML_anchor; 1013 1014 // Ein HREF nur Ausgaben, wenn es einen Link oder Makros gibt 1015 if( aMapURL.Len() || bEvents ) 1016 { 1017 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_href) += "=\""; 1018 rWrt.Strm() << sOut.GetBuffer(); 1019 rHTMLWrt.OutHyperlinkHRefValue( aMapURL ); 1020 sOut = '\"'; 1021 } 1022 1023 if( aName.Len() ) 1024 { 1025 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_name) += "=\""; 1026 rWrt.Strm() << sOut.GetBuffer(); 1027 HTMLOutFuncs::Out_String( rWrt.Strm(), aName, 1028 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); 1029 sOut = '\"'; 1030 } 1031 1032 if( aTarget.Len() ) 1033 { 1034 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_target) += "=\""; 1035 rWrt.Strm() << sOut.GetBuffer(); 1036 HTMLOutFuncs::Out_String( rWrt.Strm(), aTarget, 1037 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); 1038 sOut = '\"'; 1039 } 1040 if( sOut.Len() ) 1041 { 1042 rWrt.Strm() << sOut.GetBuffer(); 1043 sOut.Erase(); 1044 } 1045 1046 if( pMacItem ) 1047 { 1048 const SvxMacroTableDtor& rMacTable = pMacItem->GetMacroTable(); 1049 if( rMacTable.Count() ) 1050 HTMLOutFuncs::Out_Events( rWrt.Strm(), rMacTable, 1051 aAnchorEventTable, 1052 rHTMLWrt.bCfgStarBasic, 1053 rHTMLWrt.eDestEnc, 1054 &rHTMLWrt.aNonConvertableCharacters ); 1055 } 1056 1057 rWrt.Strm() << ">"; 1058 (((sOut = "</") += OOO_STRING_SVTOOLS_HTML_anchor) += ">") += aEndTags; 1059 aEndTags = sOut; 1060 } 1061 } 1062 1063 // Umrandung -> <FONT COLOR = ...>...<IMG ... >...</FONT> 1064 sal_uInt16 nBorderWidth = 0; 1065 if( (nFrmOpts & HTML_FRMOPT_BORDER) && 1066 SFX_ITEM_SET == rItemSet.GetItemState( RES_BOX, sal_True, &pItem )) 1067 { 1068 Size aTwipBorder( 0, 0 ); 1069 const SvxBoxItem* pBoxItem = (const SvxBoxItem*)pItem; 1070 1071 const SvxBorderLine *pColBorderLine = 0; 1072 const SvxBorderLine *pBorderLine = pBoxItem->GetLeft(); 1073 if( pBorderLine ) 1074 { 1075 pColBorderLine = pBorderLine; 1076 aTwipBorder.Width() += pBorderLine->GetOutWidth(); 1077 } 1078 1079 pBorderLine = pBoxItem->GetRight(); 1080 if( pBorderLine ) 1081 { 1082 pColBorderLine = pBorderLine; 1083 aTwipBorder.Width() += pBorderLine->GetOutWidth(); 1084 } 1085 1086 pBorderLine = pBoxItem->GetTop(); 1087 if( pBorderLine ) 1088 { 1089 pColBorderLine = pBorderLine; 1090 aTwipBorder.Height() += pBorderLine->GetOutWidth(); 1091 } 1092 1093 pBorderLine = pBoxItem->GetBottom(); 1094 if( pBorderLine ) 1095 { 1096 pColBorderLine = pBorderLine; 1097 aTwipBorder.Height() += pBorderLine->GetOutWidth(); 1098 } 1099 1100 aTwipBorder.Width() /= 2; 1101 aTwipBorder.Height() /= 2; 1102 1103 if( (aTwipBorder.Width() || aTwipBorder.Height()) && 1104 Application::GetDefaultDevice() ) 1105 { 1106 Size aPixelBorder = 1107 Application::GetDefaultDevice()->LogicToPixel( aTwipBorder, 1108 MapMode(MAP_TWIP) ); 1109 if( !aPixelBorder.Width() && aTwipBorder.Width() ) 1110 aPixelBorder.Width() = 1; 1111 if( !aPixelBorder.Height() && aTwipBorder.Height() ) 1112 aPixelBorder.Height() = 1; 1113 1114 if( aPixelBorder.Width() ) 1115 aPixelBorder.Height() = 0; 1116 1117 nBorderWidth = 1118 (sal_uInt16)(aPixelBorder.Width() + aPixelBorder.Height()); 1119 } 1120 1121 if( pColBorderLine ) 1122 { 1123 sOut = '<'; 1124 (((sOut += OOO_STRING_SVTOOLS_HTML_font) += ' ') += OOO_STRING_SVTOOLS_HTML_O_color) += '='; 1125 rWrt.Strm() << sOut.GetBuffer(); 1126 HTMLOutFuncs::Out_Color( rWrt.Strm(), 1127 pColBorderLine->GetColor(), rHTMLWrt.eDestEnc ) << '>'; 1128 1129 (((sOut = "</" ) += OOO_STRING_SVTOOLS_HTML_font) += '>') += aEndTags; 1130 aEndTags = sOut; 1131 } 1132 } 1133 1134 sOut = '<'; 1135 (((sOut += OOO_STRING_SVTOOLS_HTML_image) += ' ') += OOO_STRING_SVTOOLS_HTML_O_src) += "=\""; 1136 rWrt.Strm() << sOut.GetBuffer(); 1137 HTMLOutFuncs::Out_String( rWrt.Strm(), aGrfNm, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ) << '\"'; 1138 1139 // Events 1140 sOut.Erase(); 1141 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRMMACRO, sal_True, &pItem )) 1142 { 1143 const SvxMacroTableDtor& rMacTable = 1144 ((const SvxMacroItem *)pItem)->GetMacroTable(); 1145 if( rMacTable.Count() ) 1146 HTMLOutFuncs::Out_Events( rWrt.Strm(), rMacTable, aImageEventTable, 1147 rHTMLWrt.bCfgStarBasic, rHTMLWrt.eDestEnc, 1148 &rHTMLWrt.aNonConvertableCharacters ); 1149 } 1150 1151 // ALT, ALIGN, WIDTH, HEIGHT, HSPACE, VSPACE 1152 rHTMLWrt.OutFrmFmtOptions( rFrmFmt, rAlternateTxt, aEndTags, nFrmOpts ); 1153 if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) ) 1154 rHTMLWrt.OutCSS1_FrmFmtOptions( rFrmFmt, nFrmOpts ); 1155 1156 1157 if( nFrmOpts & HTML_FRMOPT_BORDER ) 1158 { 1159 (((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_border) += '=') 1160 += ByteString::CreateFromInt32( nBorderWidth ); 1161 rWrt.Strm() << sOut.GetBuffer(); 1162 } 1163 1164 if( pURLItem && pURLItem->IsServerMap() ) 1165 { 1166 (sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_ismap; 1167 rWrt.Strm() << sOut.GetBuffer(); 1168 } 1169 if( aIMapName.Len() ) 1170 { 1171 ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_usemap) += "=\"#"; 1172 rWrt.Strm() << sOut.GetBuffer(); 1173 HTMLOutFuncs::Out_String( rWrt.Strm(), aIMapName, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ) << '\"'; 1174 } 1175 1176 rHTMLWrt.Strm() << '>'; 1177 1178 if( aEndTags.Len() ) 1179 rWrt.Strm() << aEndTags.GetBuffer(); 1180 1181 if( rHTMLWrt.aINetFmts.Count() ) 1182 { 1183 // es ist noch ein Attribut auf dem Stack, das wieder geoeffnet 1184 // werden muss 1185 SwFmtINetFmt *pINetFmt = 1186 rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ]; 1187 OutHTML_INetFmt( rWrt, *pINetFmt, sal_True ); 1188 } 1189 1190 return rHTMLWrt; 1191 } 1192 1193 Writer& OutHTML_BulletImage( Writer& rWrt, 1194 const sal_Char *pTag, 1195 const SvxBrushItem* pBrush, 1196 String &rGrfName, 1197 const Size &rSize, 1198 const SwFmtVertOrient* pVertOrient ) 1199 { 1200 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 1201 1202 // Wenn es ein BrushItem gibt, muss die Grafiknoch exportiert werden 1203 const String *pLink = 0; 1204 if( pBrush ) 1205 { 1206 pLink = pBrush->GetGraphicLink(); 1207 1208 // embeddete Grafik -> WriteEmbedded schreiben 1209 if( !pLink ) 1210 { 1211 const Graphic* pGrf = pBrush->GetGraphic(); 1212 if( pGrf ) 1213 { 1214 // Grafik als (JPG-)File speichern 1215 if( rHTMLWrt.GetOrigFileName() ) 1216 rGrfName = *rHTMLWrt.GetOrigFileName(); 1217 sal_uInt16 nErr = XOutBitmap::WriteGraphic( *pGrf, rGrfName, 1218 String::CreateFromAscii("JPG"), 1219 (XOUTBMP_USE_GIF_IF_SENSIBLE | 1220 XOUTBMP_USE_NATIVE_IF_POSSIBLE)); 1221 if( !nErr ) 1222 { 1223 rGrfName = URIHelper::SmartRel2Abs( 1224 INetURLObject( rWrt.GetBaseURL() ), rGrfName, 1225 URIHelper::GetMaybeFileHdl() ); 1226 pLink = &rGrfName; 1227 } 1228 else 1229 { 1230 rHTMLWrt.nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE; 1231 } 1232 } 1233 } 1234 else 1235 { 1236 rGrfName = *pLink; 1237 if( rHTMLWrt.bCfgCpyLinkedGrfs ) 1238 { 1239 rHTMLWrt.CopyLocalFileToINet( rGrfName ); 1240 pLink = &rGrfName; 1241 } 1242 } 1243 } 1244 else 1245 { 1246 pLink = &rGrfName; 1247 } 1248 1249 ByteString sOut; 1250 if( pTag ) 1251 (sOut += '<') += pTag; 1252 1253 if( pLink ) 1254 { 1255 sOut += ' '; 1256 String s( *pLink ); 1257 if( !HTMLOutFuncs::PrivateURLToInternalImg(s) ) 1258 s = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(), s); 1259 (sOut += OOO_STRING_SVTOOLS_HTML_O_src) += "=\""; 1260 rWrt.Strm() << sOut.GetBuffer(); 1261 HTMLOutFuncs::Out_String( rWrt.Strm(), s, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); 1262 sOut = '\"'; 1263 1264 // Groesse des Objekts Twips ohne Raender 1265 Size aPixelSz( 0, 0 ); 1266 if( (rSize.Width() || rSize.Height()) && Application::GetDefaultDevice() ) 1267 { 1268 aPixelSz = 1269 Application::GetDefaultDevice()->LogicToPixel( rSize, 1270 MapMode(MAP_TWIP) ); 1271 if( !aPixelSz.Width() && rSize.Width() ) 1272 aPixelSz.Width() = 1; 1273 if( !aPixelSz.Height() && rSize.Height() ) 1274 aPixelSz.Height() = 1; 1275 } 1276 1277 if( aPixelSz.Width() ) 1278 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width) += '=') 1279 += ByteString::CreateFromInt32( aPixelSz.Width() ); 1280 1281 if( aPixelSz.Height() ) 1282 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_height) += '=') 1283 += ByteString::CreateFromInt32( aPixelSz.Height() ); 1284 1285 if( pVertOrient ) 1286 { 1287 const sal_Char *pStr = 0; 1288 switch( pVertOrient->GetVertOrient() ) 1289 { 1290 case text::VertOrientation::LINE_TOP: pStr = OOO_STRING_SVTOOLS_HTML_VA_top; break; 1291 case text::VertOrientation::CHAR_TOP: 1292 case text::VertOrientation::BOTTOM: pStr = OOO_STRING_SVTOOLS_HTML_VA_texttop; break; // geht nicht 1293 case text::VertOrientation::LINE_CENTER: 1294 case text::VertOrientation::CHAR_CENTER: pStr = OOO_STRING_SVTOOLS_HTML_VA_absmiddle; break; // geht nicht 1295 case text::VertOrientation::CENTER: pStr = OOO_STRING_SVTOOLS_HTML_VA_middle; break; 1296 case text::VertOrientation::LINE_BOTTOM: 1297 case text::VertOrientation::CHAR_BOTTOM: pStr = OOO_STRING_SVTOOLS_HTML_VA_absbottom; break; // geht nicht 1298 case text::VertOrientation::TOP: pStr = OOO_STRING_SVTOOLS_HTML_VA_bottom; break; 1299 case text::VertOrientation::NONE: break; 1300 } 1301 if( pStr ) 1302 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += pStr; 1303 } 1304 } 1305 1306 if( pTag ) 1307 sOut += '>'; 1308 rWrt.Strm() << sOut.GetBuffer(); 1309 1310 return rWrt; 1311 } 1312 1313 1314 //----------------------------------------------------------------------- 1315 1316 static Writer& OutHTML_FrmFmtTableNode( Writer& rWrt, const SwFrmFmt& rFrmFmt ) 1317 { 1318 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 1319 1320 const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt(); 1321 sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex()+1; 1322 sal_uLong nEnd = rHTMLWrt.pDoc->GetNodes()[nStt-1]->EndOfSectionIndex(); 1323 1324 String aCaption; 1325 sal_Bool bTopCaption = sal_False; 1326 1327 // Nicht const, weil GetTable spater mal nicht const ist 1328 SwNode *pNd = rHTMLWrt.pDoc->GetNodes()[ nStt ]; 1329 SwTableNode *pTblNd = pNd->GetTableNode(); 1330 const SwTxtNode *pTxtNd = pNd->GetTxtNode(); 1331 if( !pTblNd && pTxtNd ) 1332 { 1333 // Tabelle mit Ueberschrift 1334 bTopCaption = sal_True; 1335 pTblNd = rHTMLWrt.pDoc->GetNodes()[nStt+1]->GetTableNode(); 1336 } 1337 ASSERT( pTblNd, "Rahmen enthaelt keine Tabelle" ); 1338 if( pTblNd ) 1339 { 1340 sal_uLong nTblEnd = pTblNd->EndOfSectionIndex(); 1341 ASSERT( nTblEnd == nEnd - 1 || 1342 (nTblEnd == nEnd - 2 && !bTopCaption), 1343 "Ungeuelter Rahmen-Inhalt fuer Tabelle" ); 1344 1345 if( nTblEnd == nEnd - 2 ) 1346 pTxtNd = rHTMLWrt.pDoc->GetNodes()[nTblEnd+1]->GetTxtNode(); 1347 } 1348 if( pTxtNd ) 1349 aCaption = pTxtNd->GetTxt(); 1350 1351 { 1352 HTMLSaveData aSaveData( rHTMLWrt, pTblNd->GetIndex()+1, 1353 pTblNd->EndOfSectionIndex(), 1354 sal_True, &rFrmFmt ); 1355 rHTMLWrt.bOutFlyFrame = sal_True; 1356 OutHTML_SwTblNode( rHTMLWrt, *pTblNd, &rFrmFmt, &aCaption, 1357 bTopCaption ); 1358 } 1359 1360 return rWrt; 1361 } 1362 1363 static Writer & OutHTML_FrmFmtAsMulticol( Writer& rWrt, 1364 const SwFrmFmt& rFrmFmt, 1365 sal_Bool bInCntnr ) 1366 { 1367 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 1368 1369 rHTMLWrt.ChangeParaToken( 0 ); 1370 1371 // Die aktulle <DL> beenden! 1372 rHTMLWrt.OutAndSetDefList( 0 ); 1373 1374 // als Multicol ausgeben 1375 if( rHTMLWrt.bLFPossible ) 1376 rHTMLWrt.OutNewLine(); 1377 1378 ByteString sOut( '<' ); 1379 sOut += OOO_STRING_SVTOOLS_HTML_multicol; 1380 1381 const SwFmtCol& rFmtCol = rFrmFmt.GetCol(); 1382 1383 // die Anzahl der Spalten als COLS ausgeben 1384 sal_uInt16 nCols = rFmtCol.GetNumCols(); 1385 if( nCols ) 1386 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_cols) += '=') 1387 += ByteString::CreateFromInt32( nCols ); 1388 1389 // die Gutter-Breite (Minimalwert) als GUTTER 1390 sal_uInt16 nGutter = rFmtCol.GetGutterWidth( sal_True ); 1391 if( nGutter!=USHRT_MAX ) 1392 { 1393 if( nGutter && Application::GetDefaultDevice() ) 1394 { 1395 nGutter = (sal_uInt16)Application::GetDefaultDevice() 1396 ->LogicToPixel( Size(nGutter,0), 1397 MapMode(MAP_TWIP) ).Width(); 1398 } 1399 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_gutter) += '=') 1400 += ByteString::CreateFromInt32( nGutter ); 1401 } 1402 1403 rWrt.Strm() << sOut.GetBuffer(); 1404 1405 // WIDTH 1406 sal_uLong nFrmFlags = bInCntnr ? HTML_FRMOPTS_MULTICOL_CNTNR 1407 : HTML_FRMOPTS_MULTICOL; 1408 if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) 1409 nFrmFlags |= HTML_FRMOPTS_MULTICOL_CSS1; 1410 ByteString aEndTags; 1411 rHTMLWrt.OutFrmFmtOptions( rFrmFmt, aEmptyStr, aEndTags, nFrmFlags ); 1412 if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) 1413 rHTMLWrt.OutCSS1_FrmFmtOptions( rFrmFmt, nFrmFlags ); 1414 1415 rWrt.Strm() << '>'; 1416 1417 rHTMLWrt.bLFPossible = sal_True; 1418 rHTMLWrt.IncIndentLevel(); // den Inhalt von Multicol einruecken; 1419 1420 const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt(); 1421 sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex(); 1422 const SwStartNode* pSttNd = rWrt.pDoc->GetNodes()[nStt]->GetStartNode(); 1423 ASSERT( pSttNd, "Wo ist der Start-Node" ); 1424 1425 { 1426 // in einem Block damit rechtzeitig vor dem Ende der alte Zustand 1427 // wieder hergestellt wird. 1428 HTMLSaveData aSaveData( rHTMLWrt, nStt+1, 1429 pSttNd->EndOfSectionIndex(), 1430 sal_True, &rFrmFmt ); 1431 rHTMLWrt.bOutFlyFrame = sal_True; 1432 rHTMLWrt.Out_SwDoc( rWrt.pCurPam ); 1433 } 1434 1435 // rHTMLWrt.ChangeParaToken( 0 ); // MIB 8.7.97: Passiert jetzt in Out_SwDoc 1436 1437 rHTMLWrt.DecIndentLevel(); // den Inhalt von Multicol einruecken; 1438 if( rHTMLWrt.bLFPossible ) 1439 rHTMLWrt.OutNewLine(); 1440 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_multicol, sal_False ); 1441 rHTMLWrt.bLFPossible = sal_True; 1442 1443 return rWrt; 1444 } 1445 1446 static Writer& OutHTML_FrmFmtAsSpacer( Writer& rWrt, const SwFrmFmt& rFrmFmt ) 1447 { 1448 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 1449 1450 // wenn meoglich vor der Grafik einen Zeilen-Umbruch ausgeben 1451 if( rHTMLWrt.bLFPossible ) 1452 rHTMLWrt.OutNewLine( sal_True ); 1453 1454 ByteString sOut('<'); 1455 ((((sOut += OOO_STRING_SVTOOLS_HTML_spacer) += ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '=') 1456 += OOO_STRING_SVTOOLS_HTML_SPTYPE_block; 1457 rWrt.Strm() << sOut.GetBuffer(); 1458 1459 // ALIGN, WIDTH, HEIGHT 1460 ByteString aEndTags; 1461 rHTMLWrt.OutFrmFmtOptions( rFrmFmt, aEmptyStr, aEndTags, 1462 HTML_FRMOPTS_SPACER ); 1463 1464 rWrt.Strm() << '>'; 1465 if( aEndTags.Len() ) 1466 rWrt.Strm() << aEndTags.GetBuffer(); 1467 1468 return rWrt; 1469 } 1470 1471 static Writer& OutHTML_FrmFmtAsDivOrSpan( Writer& rWrt, 1472 const SwFrmFmt& rFrmFmt, sal_Bool bSpan) 1473 { 1474 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 1475 1476 const sal_Char *pStr = 0; 1477 if( !bSpan ) 1478 { 1479 rHTMLWrt.ChangeParaToken( 0 ); 1480 1481 // Die aktulle <DL> beenden! 1482 rHTMLWrt.OutAndSetDefList( 0 ); 1483 pStr = OOO_STRING_SVTOOLS_HTML_division; 1484 } 1485 else 1486 pStr = OOO_STRING_SVTOOLS_HTML_span; 1487 1488 // als DIV ausgeben 1489 if( rHTMLWrt.bLFPossible ) 1490 rHTMLWrt.OutNewLine(); 1491 1492 ByteString sOut( '<' ); 1493 sOut += pStr; 1494 1495 rWrt.Strm() << sOut.GetBuffer(); 1496 ByteString aEndTags; 1497 sal_uLong nFrmFlags = HTML_FRMOPTS_DIV; 1498 if( rHTMLWrt.IsHTMLMode( HTMLMODE_BORDER_NONE ) ) 1499 nFrmFlags |= HTML_FRMOPT_S_NOBORDER; 1500 rHTMLWrt.OutFrmFmtOptions( rFrmFmt, aEmptyStr, aEndTags, nFrmFlags ); 1501 rHTMLWrt.OutCSS1_FrmFmtOptions( rFrmFmt, nFrmFlags ); 1502 rWrt.Strm() << '>'; 1503 1504 rHTMLWrt.IncIndentLevel(); // den Inhalt einruecken 1505 rHTMLWrt.bLFPossible = sal_True; 1506 1507 const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt(); 1508 sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex(); 1509 1510 // Am Start-Node verankerte Rahmen-gebundene Rahmen ausgeben 1511 rHTMLWrt.OutFlyFrm( nStt, 0, HTML_POS_ANY ); 1512 1513 const SwStartNode* pSttNd = rWrt.pDoc->GetNodes()[nStt]->GetStartNode(); 1514 ASSERT( pSttNd, "Wo ist der Start-Node" ); 1515 1516 { 1517 // in einem Block damit rechtzeitig vor dem Ende der alte Zustand 1518 // wieder hergestellt wird. 1519 HTMLSaveData aSaveData( rHTMLWrt, nStt+1, 1520 pSttNd->EndOfSectionIndex(), 1521 sal_True, &rFrmFmt ); 1522 rHTMLWrt.bOutFlyFrame = sal_True; 1523 rHTMLWrt.Out_SwDoc( rWrt.pCurPam ); 1524 } 1525 1526 rHTMLWrt.DecIndentLevel(); // den Inhalt von Multicol einruecken; 1527 if( rHTMLWrt.bLFPossible ) 1528 rHTMLWrt.OutNewLine(); 1529 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), pStr, sal_False ); 1530 1531 if( aEndTags.Len() ) 1532 rWrt.Strm() << aEndTags.GetBuffer(); 1533 1534 return rWrt; 1535 } 1536 1537 static Writer & OutHTML_FrmFmtAsImage( Writer& rWrt, const SwFrmFmt& rFrmFmt, 1538 sal_Bool /*bInCntnr*/ ) 1539 { 1540 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 1541 1542 ImageMap aIMap; 1543 Graphic aGrf( ((SwFrmFmt &)rFrmFmt).MakeGraphic( &aIMap ) ); 1544 1545 String aGrfNm; 1546 if( rHTMLWrt.GetOrigFileName() ) 1547 aGrfNm = *rHTMLWrt.GetOrigFileName(); 1548 if( aGrf.GetType() == GRAPHIC_NONE || 1549 XOutBitmap::WriteGraphic( aGrf, aGrfNm, 1550 String::CreateFromAscii( "JPG" ), 1551 (XOUTBMP_USE_GIF_IF_POSSIBLE| 1552 XOUTBMP_USE_NATIVE_IF_POSSIBLE) ) != 0 ) 1553 { 1554 // leer oder fehlerhaft, da ist nichts auszugeben 1555 rHTMLWrt.nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE; 1556 return rWrt; 1557 } 1558 1559 aGrfNm = URIHelper::SmartRel2Abs( 1560 INetURLObject(rWrt.GetBaseURL()), aGrfNm, 1561 URIHelper::GetMaybeFileHdl() ); 1562 Size aSz( 0, 0 ); 1563 OutHTML_Image( rWrt, rFrmFmt, aGrfNm, rFrmFmt.GetName(), aSz, 1564 HTML_FRMOPTS_GENIMG, pMarkToFrame, 1565 aIMap.GetIMapObjectCount() ? &aIMap : 0 ); 1566 return rWrt; 1567 } 1568 1569 1570 static Writer& OutHTML_FrmFmtGrfNode( Writer& rWrt, const SwFrmFmt& rFrmFmt, 1571 sal_Bool bInCntnr ) 1572 { 1573 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; 1574 1575 const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt(); 1576 sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex()+1; 1577 SwGrfNode *pGrfNd = rHTMLWrt.pDoc->GetNodes()[ nStt ]->GetGrfNode(); 1578 ASSERT( pGrfNd, "Grf-Node erwartet" ); 1579 if( !pGrfNd ) 1580 return rWrt; 1581 1582 const SwMirrorGrf& rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf(); 1583 1584 String aGrfNm; 1585 if( !pGrfNd->IsLinkedFile() || RES_MIRROR_GRAPH_DONT != rMirror.GetValue() ) 1586 { 1587 // Grafik als File-Referenz speichern (als JPEG-Grafik speichern) 1588 if( rHTMLWrt.GetOrigFileName() ) 1589 aGrfNm = *rHTMLWrt.GetOrigFileName(); 1590 pGrfNd->SwapIn( sal_True ); 1591 1592 sal_uLong nFlags = XOUTBMP_USE_GIF_IF_SENSIBLE | 1593 XOUTBMP_USE_NATIVE_IF_POSSIBLE; 1594 switch( rMirror.GetValue() ) 1595 { 1596 case RES_MIRROR_GRAPH_VERT: nFlags = XOUTBMP_MIRROR_HORZ; break; 1597 case RES_MIRROR_GRAPH_HOR: nFlags = XOUTBMP_MIRROR_VERT; break; 1598 case RES_MIRROR_GRAPH_BOTH: 1599 nFlags = XOUTBMP_MIRROR_VERT | XOUTBMP_MIRROR_HORZ; 1600 break; 1601 } 1602 1603 Size aMM100Size; 1604 const SwFmtFrmSize& rSize = rFrmFmt.GetFrmSize(); 1605 aMM100Size = OutputDevice::LogicToLogic( rSize.GetSize(), 1606 MapMode( MAP_TWIP ), MapMode( MAP_100TH_MM )); 1607 1608 sal_uInt16 nErr = XOutBitmap::WriteGraphic( pGrfNd->GetGrf(), aGrfNm, 1609 String::CreateFromAscii("JPG"), nFlags, &aMM100Size ); 1610 if( nErr ) // fehlerhaft, da ist nichts auszugeben 1611 { 1612 rHTMLWrt.nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE; 1613 return rWrt; 1614 } 1615 aGrfNm = URIHelper::SmartRel2Abs( 1616 INetURLObject(rWrt.GetBaseURL()), aGrfNm, 1617 URIHelper::GetMaybeFileHdl() ); 1618 } 1619 else 1620 { 1621 pGrfNd->GetFileFilterNms( &aGrfNm, 0 ); 1622 if( rHTMLWrt.bCfgCpyLinkedGrfs ) 1623 rWrt.CopyLocalFileToINet( aGrfNm ); 1624 } 1625 1626 sal_uLong nFrmFlags = bInCntnr ? HTML_FRMOPTS_IMG_CNTNR : HTML_FRMOPTS_IMG; 1627 if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) 1628 nFrmFlags |= HTML_FRMOPTS_IMG_CSS1; 1629 OutHTML_Image( rWrt, rFrmFmt, aGrfNm, pGrfNd->GetTitle(), 1630 pGrfNd->GetTwipSize(), nFrmFlags, pMarkToGraphic ); 1631 1632 return rWrt; 1633 } 1634 1635 1636 static Writer& OutHTML_FrmFmtAsMarquee( Writer& rWrt, const SwFrmFmt& rFrmFmt, 1637 const SdrObject& rSdrObj ) 1638 { 1639 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 1640 1641 // die Edit-Engine-Attribute des Objekts als SW-Attribute holen 1642 // und als Hints einsortieren 1643 const SfxItemSet& rFmtItemSet = rFrmFmt.GetAttrSet(); 1644 SfxItemSet aItemSet( *rFmtItemSet.GetPool(), RES_CHRATR_BEGIN, 1645 RES_CHRATR_END ); 1646 SwHTMLWriter::GetEEAttrsFromDrwObj( aItemSet, &rSdrObj, sal_True ); 1647 sal_Bool bCfgOutStylesOld = rHTMLWrt.bCfgOutStyles; 1648 rHTMLWrt.bCfgOutStyles = sal_False; 1649 rHTMLWrt.bTxtAttr = sal_True; 1650 rHTMLWrt.bTagOn = sal_True; 1651 Out_SfxItemSet( aHTMLAttrFnTab, rWrt, aItemSet, sal_False ); 1652 rHTMLWrt.bTxtAttr = sal_False; 1653 1654 OutHTML_DrawFrmFmtAsMarquee( rHTMLWrt, 1655 (const SwDrawFrmFmt &)rFrmFmt, 1656 rSdrObj ); 1657 rHTMLWrt.bTxtAttr = sal_True; 1658 rHTMLWrt.bTagOn = sal_False; 1659 Out_SfxItemSet( aHTMLAttrFnTab, rWrt, aItemSet, sal_False ); 1660 rHTMLWrt.bTxtAttr = sal_False; 1661 rHTMLWrt.bCfgOutStyles = bCfgOutStylesOld; 1662 1663 return rWrt; 1664 } 1665 1666 //----------------------------------------------------------------------- 1667 1668 Writer& OutHTML_HeaderFooter( Writer& rWrt, const SwFrmFmt& rFrmFmt, 1669 sal_Bool bHeader ) 1670 { 1671 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; 1672 1673 // als Multicol ausgeben 1674 rHTMLWrt.OutNewLine(); 1675 ByteString sOut( OOO_STRING_SVTOOLS_HTML_division ); 1676 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '='; 1677 sOut += (bHeader ? "HEADER" : "FOOTER" ); 1678 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), sOut.GetBuffer() ); 1679 1680 rHTMLWrt.IncIndentLevel(); // den Inhalt von Multicol einruecken; 1681 1682 // Einen Spacer fuer den Absatnd zusammenbasteln. Da durch das 1683 // <DL> bzw. </DL> immer einer Absatz-Abstand entsteht, wird der 1684 // ggf. abgezogen. 1685 const SvxULSpaceItem& rULSpace = rFrmFmt.GetULSpace(); 1686 sal_uInt16 nSize = bHeader ? rULSpace.GetLower() : rULSpace.GetUpper(); 1687 rHTMLWrt.nHeaderFooterSpace = nSize; 1688 1689 ByteString aSpacer; 1690 if( rHTMLWrt.IsHTMLMode(HTMLMODE_VERT_SPACER) && 1691 nSize > HTML_PARSPACE && Application::GetDefaultDevice() ) 1692 { 1693 nSize -= HTML_PARSPACE; 1694 nSize = (sal_Int16)Application::GetDefaultDevice() 1695 ->LogicToPixel( Size(nSize,0), MapMode(MAP_TWIP) ).Width(); 1696 1697 ((((((((aSpacer = OOO_STRING_SVTOOLS_HTML_spacer) += ' ') 1698 += OOO_STRING_SVTOOLS_HTML_O_type) += '=') += OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical) += ' ') 1699 += OOO_STRING_SVTOOLS_HTML_O_size) += '=') += ByteString::CreateFromInt32(nSize); 1700 } 1701 1702 const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt(); 1703 sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex(); 1704 const SwStartNode* pSttNd = rWrt.pDoc->GetNodes()[nStt]->GetStartNode(); 1705 ASSERT( pSttNd, "Wo ist der Start-Node" ); 1706 1707 if( !bHeader && aSpacer.Len() ) 1708 { 1709 rHTMLWrt.OutNewLine(); 1710 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), aSpacer.GetBuffer() ); 1711 } 1712 1713 { 1714 // in einem Block damit rechtzeitig vor dem Ende der alte Zustand 1715 // wieder hergestellt wird. pFlyFmt braucht hier nicht gestzt zu 1716 // werden, denn PageDesc-Attribute koennen hier nicht vorkommen 1717 HTMLSaveData aSaveData( rHTMLWrt, nStt+1, 1718 pSttNd->EndOfSectionIndex() ); 1719 1720 if( bHeader ) 1721 rHTMLWrt.bOutHeader = sal_True; 1722 else 1723 rHTMLWrt.bOutFooter = sal_True; 1724 1725 rHTMLWrt.Out_SwDoc( rWrt.pCurPam ); 1726 } 1727 1728 if( bHeader && aSpacer.Len() ) 1729 { 1730 rHTMLWrt.OutNewLine(); 1731 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), aSpacer.GetBuffer() ); 1732 } 1733 1734 rHTMLWrt.DecIndentLevel(); // den Inhalt von Multicol einruecken; 1735 rHTMLWrt.OutNewLine(); 1736 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_division, sal_False ); 1737 1738 rHTMLWrt.nHeaderFooterSpace = 0; 1739 1740 return rWrt; 1741 } 1742 1743 1744 void SwHTMLWriter::AddLinkTarget( const String& rURL ) 1745 { 1746 if( !rURL.Len() || rURL.GetChar(0) != '#' ) 1747 return; 1748 1749 // There might be a '|' as delimiter (if the link has been inserted 1750 // freshly) or a '%7c' or a '%7C' if the document has been saved and 1751 // loaded already. 1752 xub_StrLen nPos = rURL.Len(); 1753 sal_Bool bFound = sal_False, bEncoded = sal_False; 1754 while( !bFound && nPos > 0 ) 1755 { 1756 sal_Unicode c = rURL.GetChar( --nPos ); 1757 switch( c ) 1758 { 1759 case cMarkSeperator: 1760 bFound = sal_True; 1761 break; 1762 case '%': 1763 bFound = (rURL.Len() - nPos) >=3 && 1764 rURL.GetChar( nPos+1 ) == '7' && 1765 ((c =rURL.GetChar( nPos+2 )) == 'C' || c == 'c'); 1766 if( bFound ) 1767 bEncoded = sal_True; 1768 } 1769 } 1770 if( !bFound || nPos < 2 ) // mindetsens "#a|..." 1771 return; 1772 1773 String aURL( rURL.Copy( 1 ) ); 1774 1775 String sCmp( aURL.Copy( bEncoded ? nPos+2 : nPos ) ); // nPos-1+1/3 (-1 wg. Erase) 1776 sCmp.EraseAllChars(); 1777 if( !sCmp.Len() ) 1778 return; 1779 1780 sCmp.ToLowerAscii(); 1781 1782 if( sCmp.EqualsAscii( pMarkToRegion ) || 1783 sCmp.EqualsAscii( pMarkToFrame ) || 1784 sCmp.EqualsAscii( pMarkToGraphic ) || 1785 sCmp.EqualsAscii( pMarkToOLE ) || 1786 sCmp.EqualsAscii( pMarkToTable ) ) 1787 { 1788 // Einfach nur in einem sortierten Array merken 1789 if( bEncoded ) 1790 { 1791 aURL.Erase( nPos, 2 ); 1792 aURL.SetChar( nPos-1, cMarkSeperator ); 1793 } 1794 aImplicitMarks.Insert( new String( aURL ) ); 1795 } 1796 else if( sCmp.EqualsAscii( pMarkToOutline ) ) 1797 { 1798 // Hier brauchen wir Position und Name. Deshalb sortieren wir 1799 // ein sal_uInt16 und ein String-Array selbst 1800 String aOutline( aURL.Copy( 0, nPos-1 ) ); 1801 SwPosition aPos( *pCurPam->GetPoint() ); 1802 if( pDoc->GotoOutline( aPos, aOutline ) ) 1803 { 1804 sal_uLong nIdx = aPos.nNode.GetIndex(); 1805 1806 sal_uInt16 nIns=0; 1807 while( nIns < aOutlineMarkPoss.Count() && 1808 aOutlineMarkPoss[nIns] < nIdx ) 1809 nIns++; 1810 1811 aOutlineMarkPoss.Insert( nIdx, nIns ); 1812 if( bEncoded ) 1813 { 1814 aURL.Erase( nPos, 2 ); 1815 aURL.SetChar( nPos-1, cMarkSeperator ); 1816 } 1817 aOutlineMarks.Insert( new String( aURL ), nIns ); 1818 } 1819 } 1820 else if( sCmp.EqualsAscii( pMarkToText ) ) 1821 { 1822 // 1823 } 1824 } 1825 1826 void SwHTMLWriter::CollectLinkTargets() 1827 { 1828 const SwFmtINetFmt* pINetFmt; 1829 const SwTxtINetFmt* pTxtAttr; 1830 const SwTxtNode* pTxtNd; 1831 1832 sal_uInt32 n, nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT ); 1833 for( n = 0; n < nMaxItems; ++n ) 1834 { 1835 if( 0 != (pINetFmt = (SwFmtINetFmt*)pDoc->GetAttrPool().GetItem2( 1836 RES_TXTATR_INETFMT, n ) ) && 1837 0 != ( pTxtAttr = pINetFmt->GetTxtINetFmt()) && 1838 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) && 1839 pTxtNd->GetNodes().IsDocNodes() ) 1840 { 1841 AddLinkTarget( pINetFmt->GetValue() ); 1842 } 1843 } 1844 1845 const SwFmtURL *pURL; 1846 nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_URL ); 1847 for( n = 0; n < nMaxItems; ++n ) 1848 { 1849 if( 0 != (pURL = (SwFmtURL*)pDoc->GetAttrPool().GetItem2( 1850 RES_URL, n ) ) ) 1851 { 1852 AddLinkTarget( pURL->GetURL() ); 1853 const ImageMap *pIMap = pURL->GetMap(); 1854 if( pIMap ) 1855 { 1856 for( sal_uInt16 i=0; i<pIMap->GetIMapObjectCount(); i++ ) 1857 { 1858 const IMapObject* pObj = pIMap->GetIMapObject( i ); 1859 if( pObj ) 1860 { 1861 AddLinkTarget( pObj->GetURL() ); 1862 } 1863 } 1864 } 1865 } 1866 } 1867 } 1868 1869 //----------------------------------------------------------------------- 1870 1871 SwHTMLPosFlyFrm::SwHTMLPosFlyFrm( const SwPosFlyFrm& rPosFly, 1872 const SdrObject *pSdrObj, 1873 sal_uInt8 nOutMode ) : 1874 pFrmFmt( &rPosFly.GetFmt() ), 1875 pSdrObject( pSdrObj ), 1876 pNdIdx( new SwNodeIndex( rPosFly.GetNdIndex() ) ), 1877 nOrdNum( rPosFly.GetOrdNum() ), 1878 nCntntIdx( 0 ), 1879 nOutputMode( nOutMode ) 1880 { 1881 const SwFmtAnchor& rAnchor = rPosFly.GetFmt().GetAnchor(); 1882 if ((FLY_AT_CHAR == rAnchor.GetAnchorId()) && 1883 HTML_POS_INSIDE == GetOutPos() ) 1884 { 1885 // Auto-gebundene Rahmen werden ein Zeichen weiter hinten 1886 // ausgegeben, weil dann die Positionierung mit Netscape 1887 // uebereinstimmt. 1888 ASSERT( rAnchor.GetCntntAnchor(), "Keine Anker-Position?" ); 1889 if( rAnchor.GetCntntAnchor() ) 1890 { 1891 nCntntIdx = rAnchor.GetCntntAnchor()->nContent.GetIndex(); 1892 sal_Int16 eHoriRel = rPosFly.GetFmt().GetHoriOrient(). 1893 GetRelationOrient(); 1894 if( text::RelOrientation::FRAME == eHoriRel || text::RelOrientation::PRINT_AREA == eHoriRel ) 1895 { 1896 const SwCntntNode *pCNd = pNdIdx->GetNode().GetCntntNode(); 1897 ASSERT( pCNd, "Kein Content-Node an PaM-Position" ); 1898 if( pCNd && nCntntIdx < pCNd->Len() ) 1899 nCntntIdx++; 1900 } 1901 } 1902 } 1903 } 1904 1905 sal_Bool SwHTMLPosFlyFrm::operator<( const SwHTMLPosFlyFrm& rFrm ) const 1906 { 1907 if( pNdIdx->GetIndex() == rFrm.pNdIdx->GetIndex() ) 1908 { 1909 if( nCntntIdx == rFrm.nCntntIdx ) 1910 { 1911 if( GetOutPos() == rFrm.GetOutPos() ) 1912 return nOrdNum < rFrm.nOrdNum; 1913 else 1914 return GetOutPos() < rFrm.GetOutPos(); 1915 } 1916 else 1917 return nCntntIdx < rFrm.nCntntIdx; 1918 } 1919 else 1920 return pNdIdx->GetIndex() < rFrm.pNdIdx->GetIndex(); 1921 } 1922 1923 1924