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 #include <stdlib.h> 29 #include <hintids.hxx> 30 #include <svl/urihelper.hxx> 31 #include <rtl/tencinfo.h> 32 #include <vcl/wrkwin.hxx> 33 #include <sfx2/linkmgr.hxx> 34 35 #include <svtools/htmlcfg.hxx> 36 #include <vcl/svapp.hxx> 37 #include <i18npool/mslangid.hxx> 38 #include <sfx2/frmhtmlw.hxx> 39 #include <svx/xoutbmp.hxx> 40 #include <svx/htmlmode.hxx> 41 #include <editeng/lrspitem.hxx> 42 #include <editeng/colritem.hxx> 43 #include <editeng/brshitem.hxx> 44 #include <editeng/fontitem.hxx> 45 #include <editeng/scripttypeitem.hxx> 46 #include <editeng/langitem.hxx> 47 #include <svl/stritem.hxx> 48 #include <editeng/frmdiritem.hxx> 49 50 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> 51 #include <com/sun/star/document/XDocumentProperties.hpp> 52 #include <com/sun/star/form/XFormsSupplier.hpp> 53 #include <com/sun/star/form/XForm.hpp> 54 #include <com/sun/star/form/XImageProducerSupplier.hpp> 55 #include <com/sun/star/form/XFormController.hpp> 56 #include <com/sun/star/container/XContainer.hpp> 57 #include <com/sun/star/container/XIndexContainer.hpp> 58 #include <com/sun/star/container/XSet.hpp> 59 #include <fmthdft.hxx> 60 #include <fmtfld.hxx> 61 #include <fmtpdsc.hxx> 62 #include <txatbase.hxx> 63 #include <frmatr.hxx> 64 #include <charfmt.hxx> 65 #include <docary.hxx> 66 #include <pam.hxx> 67 #include <doc.hxx> 68 #include <ndtxt.hxx> 69 #include <mdiexp.hxx> // ...Percent() 70 #include <fltini.hxx> 71 #include <viewopt.hxx> 72 #include <IMark.hxx> // fuer SwBookmark ... 73 #include <poolfmt.hxx> 74 #include <pagedesc.hxx> 75 #include <section.hxx> 76 #include <swtable.hxx> 77 #include <fldbas.hxx> 78 #include <fmtclds.hxx> 79 #ifndef _DOCSH_HXX 80 #include <docsh.hxx> 81 #endif 82 #include <wrthtml.hxx> 83 #include <htmlnum.hxx> 84 #include <htmlfly.hxx> 85 #include <swmodule.hxx> 86 87 #ifndef _STATSTR_HRC 88 #include <statstr.hrc> // ResId fuer Statusleiste 89 #endif 90 #include <swerror.h> 91 92 #define MAX_INDENT_LEVEL 20 93 94 #if defined(UNX) 95 const sal_Char SwHTMLWriter::sNewLine = '\012'; 96 #else 97 const sal_Char __FAR_DATA SwHTMLWriter::sNewLine[] = "\015\012"; 98 #endif 99 100 static sal_Char __FAR_DATA sIndentTabs[MAX_INDENT_LEVEL+2] = 101 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; 102 103 SwHTMLWriter::SwHTMLWriter( const String& rBaseURL ) 104 { 105 SetBaseURL( rBaseURL ); 106 bFirstLine = sal_True; 107 nBkmkTabPos = -1; 108 pDfltColor = 0; 109 nImgMapCnt = 1; 110 pStartNdIdx = 0; 111 pTemplate = 0; 112 pNumRuleInfo = new SwHTMLNumRuleInfo; 113 pNextNumRuleInfo = 0; 114 pFootEndNotes = 0; 115 pFmtFtn = 0; 116 eDestEnc = RTL_TEXTENCODING_MS_1252; 117 nDirection = FRMDIR_HORI_LEFT_TOP; 118 } 119 120 121 __EXPORT SwHTMLWriter::~SwHTMLWriter() 122 { 123 delete pNumRuleInfo; 124 } 125 126 sal_uLong SwHTMLWriter::WriteStream() 127 { 128 // neue Konfiguration setzen 129 SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get(); 130 131 // die Fontgroessen 1-7 132 aFontHeights[0] = pHtmlOptions->GetFontSize( 0 ) * 20; 133 aFontHeights[1] = pHtmlOptions->GetFontSize( 1 ) * 20; 134 aFontHeights[2] = pHtmlOptions->GetFontSize( 2 ) * 20; 135 aFontHeights[3] = pHtmlOptions->GetFontSize( 3 ) * 20; 136 aFontHeights[4] = pHtmlOptions->GetFontSize( 4 ) * 20; 137 aFontHeights[5] = pHtmlOptions->GetFontSize( 5 ) * 20; 138 aFontHeights[6] = pHtmlOptions->GetFontSize( 6 ) * 20; 139 140 // ueberhaupt Styles ausgeben 141 // (dann auch obere und untere Absatz-Abstaende) 142 nExportMode = pHtmlOptions->GetExportMode(); 143 nHTMLMode = GetHtmlMode(0); 144 if( HTML_CFG_WRITER==nExportMode || 145 HTML_CFG_NS40==nExportMode ) 146 nHTMLMode |= HTMLMODE_BLOCK_SPACER; 147 148 if( HTML_CFG_WRITER==nExportMode || HTML_CFG_MSIE==nExportMode ) 149 nHTMLMode |= (HTMLMODE_FLOAT_FRAME | HTMLMODE_LSPACE_IN_NUMBUL); 150 151 if( HTML_CFG_MSIE==nExportMode ) 152 nHTMLMode |= HTMLMODE_NBSP_IN_TABLES; 153 154 if( HTML_CFG_WRITER==nExportMode || HTML_CFG_NS40==nExportMode || 155 HTML_CFG_MSIE==nExportMode ) 156 nHTMLMode |= HTMLMODE_ABS_POS_FLY|HTMLMODE_ABS_POS_DRAW; 157 158 if( HTML_CFG_WRITER==nExportMode ) 159 // nHTMLMode |= HTMLMODE_FLY_MARGINS | HTMLMODE_FRSTLINE_IN_NUMBUL; 160 nHTMLMode |= HTMLMODE_FLY_MARGINS; 161 162 if( HTML_CFG_NS40==nExportMode ) 163 nHTMLMode |= HTMLMODE_BORDER_NONE; 164 165 if( HTML_CFG_HTML32!=nExportMode ) 166 nHTMLMode |= HTMLMODE_FONT_GENERIC; 167 168 if( HTML_CFG_NS40==nExportMode ) 169 nHTMLMode |= HTMLMODE_NO_CONTROL_CENTERING; 170 171 bCfgOutStyles = IsHTMLMode(HTMLMODE_SOME_STYLES | 172 HTMLMODE_FULL_STYLES); 173 bCfgNetscape4 = (HTML_CFG_NS40==nExportMode); 174 175 if( IsHTMLMode(HTMLMODE_SOME_STYLES | HTMLMODE_FULL_STYLES) ) 176 nHTMLMode |= HTMLMODE_PRINT_EXT; 177 178 const sal_Char *pHelpHack = getenv( "HelpEx" ); 179 if( pHelpHack ) 180 { 181 ByteString aTmp( pHelpHack ); 182 if( aTmp.EqualsIgnoreCaseAscii( "Hilfe" ) ) 183 nHTMLMode |= HTMLMODE_NO_BR_AT_PAREND; 184 } 185 186 eCSS1Unit = (FieldUnit)SW_MOD()->GetMetric( pDoc->get(IDocumentSettingAccess::HTML_MODE) ); 187 188 sal_Bool bWriteUTF8 = bWriteClipboardDoc; 189 eDestEnc = bWriteUTF8 ? RTL_TEXTENCODING_UTF8 190 : pHtmlOptions->GetTextEncoding(); 191 const sal_Char *pCharSet = 192 rtl_getBestMimeCharsetFromTextEncoding( eDestEnc ); 193 eDestEnc = rtl_getTextEncodingFromMimeCharset( pCharSet ); 194 195 // fuer Netscape optimieren heisst Spacer- und Multicol ausgeben 196 // bCfgMultiCol = pHtmlOptions->IsNetscape3(); 197 // bCfgSpacer = pHtmlOptions->IsNetscape3(); 198 199 // wenn Styles exportiert werden, wird ein Style einem HTML-Tag manchmal 200 // vorgezogen, wenn nicht fuer Netscape exportiert wird 201 // bCfgPreferStyles = bCfgOutStyles; // && !pHtmlOptions->IsNetscape3(); 202 203 // Nur noch fuer den MS-IE ziehen wir den Export von Styles vor. 204 bCfgPreferStyles = HTML_CFG_MSIE==nExportMode; 205 206 bCfgStarBasic = pHtmlOptions->IsStarBasic(); 207 208 bCfgFormFeed = !IsHTMLMode(HTMLMODE_PRINT_EXT); 209 bCfgCpyLinkedGrfs = pHtmlOptions->IsSaveGraphicsLocal(); 210 211 // die HTML-Vorlage holen 212 sal_Bool bOldHTMLMode = sal_False; 213 sal_uInt16 nOldTxtFmtCollCnt = 0, nOldCharFmtCnt = 0; 214 215 ASSERT( !pTemplate, "Wo kommt denn die HTML-Vorlage hier her?" ); 216 pTemplate = ((HTMLReader*)ReadHTML)->GetTemplateDoc(); 217 if( pTemplate ) 218 { 219 pTemplate->acquire(); 220 bOldHTMLMode = pTemplate->get(IDocumentSettingAccess::HTML_MODE); 221 pTemplate->set(IDocumentSettingAccess::HTML_MODE, true); 222 223 nOldTxtFmtCollCnt = pTemplate->GetTxtFmtColls()->Count(); 224 nOldCharFmtCnt = pTemplate->GetCharFmts()->Count(); 225 } 226 227 if( bShowProgress ) 228 ::StartProgress( STR_STATSTR_W4WWRITE, 0, pDoc->GetNodes().Count(), 229 pDoc->GetDocShell()); 230 231 pDfltColor = 0; 232 pFootEndNotes = 0; 233 pFmtFtn = 0; 234 bOutTable = bOutHeader = bOutFooter = bOutFlyFrame = sal_False; 235 pxFormComps = 0; 236 nFormCntrlCnt = 0; 237 bPreserveForm = sal_False; 238 bClearLeft = bClearRight = sal_False; 239 bLFPossible = sal_False; 240 241 nLeftMargin = nDfltLeftMargin = nDfltRightMargin = 0; 242 nDfltTopMargin = nDfltBottomMargin = 0; 243 nFirstLineIndent = nDfltFirstLineIndent = 0; 244 bPoolCollTextModified = sal_False; 245 bFirstCSS1Property = bFirstCSS1Rule = sal_False; 246 bCSS1IgnoreFirstPageDesc = sal_False; 247 nIndentLvl = 0; 248 nWhishLineLen = 70; 249 nLastLFPos = 0; 250 nDefListLvl = 0; 251 nDefListMargin = ((pTemplate && !bCfgOutStyles) ? pTemplate : pDoc) 252 ->GetTxtCollFromPool( RES_POOLCOLL_HTML_DD, false ) 253 ->GetLRSpace().GetTxtLeft(); 254 nHeaderFooterSpace = 0; 255 nTxtAttrsToIgnore = 0; 256 nCSS1OutMode = 0; 257 sal_uInt16 nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( 258 static_cast< LanguageType >( GetAppLanguage() ) ); 259 switch( nScript ) 260 { 261 case SCRIPTTYPE_ASIAN: 262 nCSS1Script = CSS1_OUTMODE_CJK; 263 break; 264 case SCRIPTTYPE_COMPLEX: 265 nCSS1Script = CSS1_OUTMODE_CTL; 266 break; 267 default: 268 nCSS1Script = CSS1_OUTMODE_WESTERN; 269 break; 270 } 271 eLang = ((const SvxLanguageItem&)pDoc 272 ->GetDefault(GetLangWhichIdFromScript(nCSS1Script))).GetLanguage(); 273 274 nFootNote = nEndNote = 0; 275 276 nWarn = 0; 277 GetNumInfo().Clear(); 278 pNextNumRuleInfo = 0; 279 280 ByteString aStartTags; 281 282 // Tabellen und Bereiche am Doc.-Anfang beachten 283 { 284 SwTableNode * pTNd = pCurPam->GetNode()->FindTableNode(); 285 if( pTNd && bWriteAll ) 286 { 287 // mit dem Tabellen-Node anfangen !! 288 pCurPam->GetPoint()->nNode = *pTNd; 289 290 if( bWriteOnlyFirstTable ) 291 pCurPam->GetMark()->nNode = *pTNd->EndOfSectionNode(); 292 } 293 294 // erster Node (der einen Seitenumbruch enthalten darf) 295 pStartNdIdx = new SwNodeIndex( pCurPam->GetPoint()->nNode ); 296 297 SwSectionNode * pSNd = pCurPam->GetNode()->FindSectionNode(); 298 while( pSNd ) 299 { 300 if( bWriteAll ) 301 { 302 // mit dem Section-Node anfangen !! 303 pCurPam->GetPoint()->nNode = *pSNd; 304 } 305 else 306 { 307 ASSERT( FILE_LINK_SECTION != pSNd->GetSection().GetType(), 308 "Export gelinkter Bereiche am Dok-Anfang ist nicht implemntiert" ); 309 310 // nur das Tag fuer die Section merken 311 ByteString aName; 312 HTMLOutFuncs::ConvertStringToHTML( 313 pSNd->GetSection().GetSectionName(), 314 aName, eDestEnc, &aNonConvertableCharacters ); 315 316 ByteString sOut( '<' ); 317 (((((((sOut += OOO_STRING_SVTOOLS_HTML_division) 318 += ' ') += OOO_STRING_SVTOOLS_HTML_O_id) += "=\"") 319 += aName) += '\"') 320 += '>') += aStartTags; 321 322 aStartTags = sOut; 323 } 324 // FindSectionNode() an einem SectionNode liefert den selben! 325 pSNd = pSNd->StartOfSectionNode()->FindSectionNode(); 326 } 327 } 328 329 330 // Tabelle fuer die freifliegenden Rahmen erzeugen, aber nur wenn 331 // das gesamte Dokument geschrieben wird 332 pHTMLPosFlyFrms = 0; 333 CollectFlyFrms(); 334 nLastParaToken = 0; 335 GetControls(); 336 CollectLinkTargets(); 337 338 sal_uInt16 nHeaderAttrs = 0; 339 pCurrPageDesc = MakeHeader( nHeaderAttrs ); 340 341 bLFPossible = sal_True; 342 343 // Formulare, die nur HiddenControls enthalten ausgeben. 344 OutHiddenForms(); 345 346 if( aStartTags.Len() ) 347 Strm() << aStartTags.GetBuffer(); 348 349 const SfxPoolItem *pItem; 350 const SfxItemSet& rPageItemSet = pCurrPageDesc->GetMaster().GetAttrSet(); 351 if( !bWriteClipboardDoc && pDoc->GetDocShell() && 352 (!pDoc->get(IDocumentSettingAccess::HTML_MODE) && 353 !pDoc->get(IDocumentSettingAccess::BROWSE_MODE)) && 354 SFX_ITEM_SET == rPageItemSet.GetItemState( RES_HEADER, sal_True, &pItem) ) 355 { 356 const SwFrmFmt *pHeaderFmt = 357 ((const SwFmtHeader *)pItem)->GetHeaderFmt(); 358 if( pHeaderFmt ) 359 OutHTML_HeaderFooter( *this, *pHeaderFmt, sal_True ); 360 } 361 362 nTxtAttrsToIgnore = nHeaderAttrs; 363 Out_SwDoc( pOrigPam ); 364 nTxtAttrsToIgnore = 0; 365 366 if( pxFormComps && pxFormComps->is() ) 367 OutForm( sal_False, *pxFormComps ); 368 369 if( pFootEndNotes ) 370 OutFootEndNotes(); 371 372 if( !bWriteClipboardDoc && pDoc->GetDocShell() && 373 (!pDoc->get(IDocumentSettingAccess::HTML_MODE) && !pDoc->get(IDocumentSettingAccess::BROWSE_MODE)) && 374 SFX_ITEM_SET == rPageItemSet.GetItemState( RES_FOOTER, sal_True, &pItem) ) 375 { 376 const SwFrmFmt *pFooterFmt = 377 ((const SwFmtFooter *)pItem)->GetFooterFmt(); 378 if( pFooterFmt ) 379 OutHTML_HeaderFooter( *this, *pFooterFmt, sal_False ); 380 } 381 382 if( bLFPossible ) 383 OutNewLine(); 384 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_body, sal_False ); 385 OutNewLine(); 386 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html, sal_False ); 387 388 // loesche die Tabelle mit den freifliegenden Rahmen 389 sal_uInt16 i; 390 ASSERT( !pHTMLPosFlyFrms, "Wurden nicht alle Rahmen ausgegeben" ); 391 if( pHTMLPosFlyFrms ) 392 { 393 pHTMLPosFlyFrms->DeleteAndDestroy( 0, pHTMLPosFlyFrms->Count() ); 394 delete pHTMLPosFlyFrms; 395 pHTMLPosFlyFrms = 0; 396 } 397 398 if( aHTMLControls.Count() ) 399 aHTMLControls.DeleteAndDestroy( sal_uInt16(0), aHTMLControls.Count() ); 400 401 if( aChrFmtInfos.Count() ) 402 aChrFmtInfos.DeleteAndDestroy( sal_uInt16(0), aChrFmtInfos.Count() ); 403 404 if( aTxtCollInfos.Count() ) 405 aTxtCollInfos.DeleteAndDestroy( sal_uInt16(0), aTxtCollInfos.Count() ); 406 407 if( aImgMapNames.Count() ) 408 aImgMapNames.DeleteAndDestroy( sal_uInt16(0), aImgMapNames.Count() ); 409 410 if( aImplicitMarks.Count() ) 411 aImplicitMarks.DeleteAndDestroy( sal_uInt16(0), aImplicitMarks.Count() ); 412 413 if( aOutlineMarks.Count() ) 414 aOutlineMarks.DeleteAndDestroy( sal_uInt16(0), aOutlineMarks.Count() ); 415 416 if( aOutlineMarkPoss.Count() ) 417 aOutlineMarkPoss.Remove( sal_uInt16(0), aOutlineMarkPoss.Count() ); 418 419 if( aNumRuleNames.Count() ) 420 aNumRuleNames.DeleteAndDestroy( sal_uInt16(0), aNumRuleNames.Count() ); 421 422 if( aScriptParaStyles.Count() ) 423 aScriptParaStyles.DeleteAndDestroy( sal_uInt16(0), aScriptParaStyles.Count() ); 424 if( aScriptTextStyles.Count() ) 425 aScriptTextStyles.DeleteAndDestroy( sal_uInt16(0), aScriptTextStyles.Count() ); 426 427 delete pDfltColor; 428 pDfltColor = 0; 429 430 delete pStartNdIdx; 431 pStartNdIdx = 0; 432 433 delete pxFormComps; 434 pxFormComps = 0; 435 436 ASSERT( !pFootEndNotes, 437 "SwHTMLWriter::Write: Ftns nicht durch OutFootEndNotes geloescht" ); 438 439 pCurrPageDesc = 0; 440 441 ClearNextNumInfo(); 442 443 for( i=0; i<MAXLEVEL; i++ ) 444 aBulletGrfs[i].Erase(); 445 446 aNonConvertableCharacters.Erase(); 447 448 if( bShowProgress ) 449 ::EndProgress( pDoc->GetDocShell() ); 450 451 if( pTemplate ) 452 { 453 // Waehrend des Exports angelegte Zeichen- und Abastzvorlagen 454 // loeschen 455 sal_uInt16 nTxtFmtCollCnt = pTemplate->GetTxtFmtColls()->Count(); 456 while( nTxtFmtCollCnt > nOldTxtFmtCollCnt ) 457 pTemplate->DelTxtFmtColl( --nTxtFmtCollCnt ); 458 ASSERT( pTemplate->GetTxtFmtColls()->Count() == nOldTxtFmtCollCnt, 459 "falsche Anzahl TxtFmtColls geloescht" ); 460 461 sal_uInt16 nCharFmtCnt = pTemplate->GetCharFmts()->Count(); 462 while( nCharFmtCnt > nOldCharFmtCnt ) 463 pTemplate->DelCharFmt( --nCharFmtCnt ); 464 ASSERT( pTemplate->GetCharFmts()->Count() == nOldCharFmtCnt, 465 "falsche Anzahl CharFmts geloescht" ); 466 467 // HTML-Modus wieder restaurieren 468 pTemplate->set(IDocumentSettingAccess::HTML_MODE, bOldHTMLMode); 469 470 if( 0 == pTemplate->release() ) 471 delete pTemplate; 472 473 pTemplate = 0; 474 } 475 476 return nWarn; 477 } 478 479 const SwFmtCol *lcl_html_GetFmtCol( const SwHTMLWriter& rHTMLWrt, 480 const SwSection& rSection, 481 const SwSectionFmt& rFmt ) 482 { 483 const SwFmtCol *pCol = 0; 484 485 const SfxPoolItem* pItem; 486 if( rHTMLWrt.IsHTMLMode( HTMLMODE_FRM_COLUMNS ) && 487 FILE_LINK_SECTION != rSection.GetType() && 488 SFX_ITEM_SET == rFmt.GetAttrSet().GetItemState(RES_COL,sal_False,&pItem) && 489 ((const SwFmtCol *)pItem)->GetNumCols() > 1 ) 490 { 491 pCol = (const SwFmtCol *)pItem; 492 } 493 494 return pCol; 495 } 496 497 sal_Bool lcl_html_IsMultiColStart( const SwHTMLWriter& rHTMLWrt, sal_uLong nIndex ) 498 { 499 sal_Bool bRet = sal_False; 500 const SwSectionNode *pSectNd = 501 rHTMLWrt.pDoc->GetNodes()[nIndex]->GetSectionNode(); 502 if( pSectNd ) 503 { 504 const SwSection& rSection = pSectNd->GetSection(); 505 const SwSectionFmt *pFmt = rSection.GetFmt(); 506 if( pFmt && lcl_html_GetFmtCol( rHTMLWrt, rSection, *pFmt ) ) 507 bRet = sal_True; 508 } 509 510 return bRet; 511 } 512 513 sal_Bool lcl_html_IsMultiColEnd( const SwHTMLWriter& rHTMLWrt, sal_uLong nIndex ) 514 { 515 sal_Bool bRet = sal_False; 516 const SwEndNode *pEndNd = rHTMLWrt.pDoc->GetNodes()[nIndex]->GetEndNode(); 517 if( pEndNd ) 518 bRet = lcl_html_IsMultiColStart( rHTMLWrt, 519 pEndNd->StartOfSectionIndex() ); 520 521 return bRet; 522 } 523 524 525 void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt, 526 const SwSection& rSection, 527 const SwSectionFmt& rFmt, 528 const SwFmtCol *pCol, 529 sal_Bool bContinued=sal_False ) 530 { 531 ASSERT( pCol || !bContinued, "Continuation of DIV" ); 532 533 if( rHTMLWrt.bLFPossible ) 534 rHTMLWrt.OutNewLine(); 535 536 const sal_Char *pTag = pCol ? OOO_STRING_SVTOOLS_HTML_multicol : OOO_STRING_SVTOOLS_HTML_division; 537 538 ByteString sOut( '<' ); 539 sOut += pTag; 540 541 const String& rName = rSection.GetSectionName(); 542 if( rName.Len() && !bContinued ) 543 { 544 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_id) += "=\""; 545 rHTMLWrt.Strm() << sOut.GetBuffer(); 546 HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), rName, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); 547 sOut = '\"'; 548 } 549 550 sal_uInt16 nDir = rHTMLWrt.GetHTMLDirection( rFmt.GetAttrSet() ); 551 rHTMLWrt.Strm() << sOut.GetBuffer(); 552 sOut.Erase(); 553 rHTMLWrt.OutDirection( nDir ); 554 555 if( FILE_LINK_SECTION == rSection.GetType() ) 556 { 557 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_href) += "=\""; 558 rHTMLWrt.Strm() << sOut.GetBuffer(); 559 560 const String& aFName = rSection.GetLinkFileName(); 561 String aURL( aFName.GetToken(0,sfx2::cTokenSeperator) ); 562 String aFilter( aFName.GetToken(1,sfx2::cTokenSeperator) ); 563 String aSection( aFName.GetToken(2,sfx2::cTokenSeperator) ); 564 565 String aEncURL( URIHelper::simpleNormalizedMakeRelative(rHTMLWrt.GetBaseURL(), aURL ) ); 566 sal_Unicode cDelim = 255U; 567 sal_Bool bURLContainsDelim = 568 (STRING_NOTFOUND != aEncURL.Search( cDelim ) ); 569 570 HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aEncURL, 571 rHTMLWrt.eDestEnc, 572 &rHTMLWrt.aNonConvertableCharacters ); 573 const sal_Char *pDelim = "ÿ"; 574 if( aFilter.Len() || aSection.Len() || bURLContainsDelim ) 575 rHTMLWrt.Strm() << pDelim; 576 if( aFilter.Len() ) 577 HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aFilter, 578 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); 579 if( aSection.Len() || bURLContainsDelim ) 580 rHTMLWrt.Strm() << pDelim; 581 if( aSection.Len() ) 582 { 583 xub_StrLen nPos = aSection.Search( '%' ); 584 while( STRING_NOTFOUND != nPos ) 585 { 586 aSection.Erase( nPos, 1 ); 587 aSection.InsertAscii( "%25", nPos ); 588 nPos = aSection.Search( '%', nPos+3 ); 589 } 590 nPos = aSection.Search( cDelim ); 591 while( STRING_NOTFOUND != nPos ) 592 { 593 aSection.Erase( nPos, 1 ); 594 aSection.InsertAscii( "%FF", nPos ); 595 nPos = aSection.Search( cDelim, nPos+3 ); 596 } 597 HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aSection, 598 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); 599 } 600 sOut = '\"'; 601 } 602 else if( pCol ) 603 { 604 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_cols) += '=') 605 += ByteString::CreateFromInt32( pCol->GetNumCols() ); 606 607 // minumum gutter width 608 sal_uInt16 nGutter = pCol->GetGutterWidth( sal_True ); 609 if( nGutter!=USHRT_MAX ) 610 { 611 if( nGutter && Application::GetDefaultDevice() ) 612 { 613 nGutter = (sal_uInt16)Application::GetDefaultDevice() 614 ->LogicToPixel( Size(nGutter,0), 615 MapMode(MAP_TWIP) ).Width(); 616 } 617 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_gutter) += '=') 618 += ByteString::CreateFromInt32( nGutter ); 619 } 620 } 621 622 rHTMLWrt.Strm() << sOut.GetBuffer(); 623 if( rHTMLWrt.IsHTMLMode( rHTMLWrt.bCfgOutStyles ) ) 624 rHTMLWrt.OutCSS1_SectionFmtOptions( rFmt ); 625 626 rHTMLWrt.Strm() << '>'; 627 628 rHTMLWrt.bLFPossible = sal_True; 629 if( rName.Len() && !bContinued ) 630 rHTMLWrt.OutImplicitMark( rName, pMarkToRegion ); 631 632 rHTMLWrt.IncIndentLevel(); 633 } 634 635 void lcl_html_OutSectionEndTag( SwHTMLWriter& rHTMLWrt, 636 const SwFmtCol *pCol ) 637 { 638 const sal_Char *pTag = pCol ? OOO_STRING_SVTOOLS_HTML_multicol : OOO_STRING_SVTOOLS_HTML_division; 639 640 rHTMLWrt.DecIndentLevel(); 641 if( rHTMLWrt.bLFPossible ) 642 rHTMLWrt.OutNewLine(); 643 HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), pTag, sal_False ); 644 rHTMLWrt.bLFPossible = sal_True; 645 } 646 647 static Writer& OutHTML_Section( Writer& rWrt, const SwSectionNode& rSectNd ) 648 { 649 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; 650 651 // End <PRE> and any <DL>, because a definition list's level may 652 // change inside the section. 653 rHTMLWrt.ChangeParaToken( 0 ); 654 rHTMLWrt.OutAndSetDefList( 0 ); 655 656 const SwSection& rSection = rSectNd.GetSection(); 657 const SwSectionFmt *pFmt = rSection.GetFmt(); 658 ASSERT( pFmt, "Section without a format?" ); 659 660 sal_Bool bStartTag = sal_True; 661 sal_Bool bEndTag = sal_True; 662 const SwSectionFmt *pSurrFmt = 0; 663 const SwSectionNode *pSurrSectNd = 0; 664 const SwSection *pSurrSection = 0; 665 const SwFmtCol *pSurrCol = 0; 666 667 sal_uInt32 nSectSttIdx = rSectNd.GetIndex(); 668 sal_uInt32 nSectEndIdx = rSectNd.EndOfSectionIndex(); 669 const SwFmtCol *pCol = lcl_html_GetFmtCol( rHTMLWrt, rSection, *pFmt ); 670 if( pCol ) 671 { 672 // If the next node is a columned section node, too, don't export 673 // an empty section. 674 if( lcl_html_IsMultiColStart( rHTMLWrt, nSectSttIdx+1 ) ) 675 bStartTag = sal_False; 676 677 // The same applies if the section end with another columned section. 678 if( lcl_html_IsMultiColEnd( rHTMLWrt, nSectEndIdx-1 ) ) 679 bEndTag = sal_False; 680 681 //.is there a columned section arround this one? 682 const SwStartNode *pSttNd = rSectNd.StartOfSectionNode(); 683 if( pSttNd ) 684 { 685 pSurrSectNd = pSttNd->FindSectionNode(); 686 if( pSurrSectNd ) 687 { 688 const SwStartNode *pBoxSttNd = pSttNd->FindTableBoxStartNode(); 689 if( !pBoxSttNd || 690 pBoxSttNd->GetIndex() < pSurrSectNd->GetIndex() ) 691 { 692 pSurrSection = &pSurrSectNd->GetSection(); 693 pSurrFmt = pSurrSection->GetFmt(); 694 if( pSurrFmt ) 695 pSurrCol = lcl_html_GetFmtCol( rHTMLWrt, *pSurrSection, 696 *pSurrFmt ); 697 } 698 } 699 } 700 } 701 702 // The surrounding section must be closed before the current one is 703 // opended, except that it start immediatly before the current one or 704 // another end immediately before the current one 705 if( pSurrCol && nSectSttIdx - pSurrSectNd->GetIndex() > 1 && 706 !lcl_html_IsMultiColEnd( rHTMLWrt, nSectSttIdx-1 ) ) 707 lcl_html_OutSectionEndTag( rHTMLWrt, pSurrCol ); 708 709 if( bStartTag ) 710 lcl_html_OutSectionStartTag( rHTMLWrt, rSection, *pFmt, pCol ); 711 712 { 713 HTMLSaveData aSaveData( rHTMLWrt, 714 rHTMLWrt.pCurPam->GetPoint()->nNode.GetIndex()+1, 715 rSectNd.EndOfSectionIndex(), 716 sal_False, pFmt ); 717 rHTMLWrt.Out_SwDoc( rHTMLWrt.pCurPam ); 718 } 719 720 rHTMLWrt.pCurPam->GetPoint()->nNode = *rSectNd.EndOfSectionNode(); 721 722 if( bEndTag ) 723 lcl_html_OutSectionEndTag( rHTMLWrt, pCol ); 724 725 // The surrounding section must be started again, except that it ends 726 // immeditaly behind the current one. 727 if( pSurrCol && 728 pSurrSectNd->EndOfSectionIndex() - nSectEndIdx > 1 && 729 !lcl_html_IsMultiColStart( rHTMLWrt, nSectEndIdx+1 ) ) 730 lcl_html_OutSectionStartTag( rHTMLWrt, *pSurrSection, *pSurrFmt, 731 pSurrCol, sal_True ); 732 733 return rWrt; 734 } 735 736 void SwHTMLWriter::Out_SwDoc( SwPaM* pPam ) 737 { 738 sal_Bool bSaveWriteAll = bWriteAll; // sichern 739 740 // suche die naechste text::Bookmark-Position aus der text::Bookmark-Tabelle 741 nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1; 742 743 // gebe alle Bereiche des Pams in das HTML-File aus. 744 do { 745 bWriteAll = bSaveWriteAll; 746 bFirstLine = sal_True; 747 748 // suche den ersten am Pam-auszugebenen FlyFrame 749 // fehlt noch: 750 751 while( pCurPam->GetPoint()->nNode.GetIndex() < pCurPam->GetMark()->nNode.GetIndex() || 752 (pCurPam->GetPoint()->nNode.GetIndex() == pCurPam->GetMark()->nNode.GetIndex() && 753 pCurPam->GetPoint()->nContent.GetIndex() <= pCurPam->GetMark()->nContent.GetIndex()) ) 754 { 755 SwNode * pNd = pCurPam->GetNode(); 756 757 ASSERT( !(pNd->IsGrfNode() || pNd->IsOLENode()), 758 "Grf- oder OLE-Node hier unerwartet" ); 759 if( pNd->IsTxtNode() ) 760 { 761 SwTxtNode* pTxtNd = pNd->GetTxtNode(); 762 763 if( !bFirstLine ) 764 pCurPam->GetPoint()->nContent.Assign( pTxtNd, 0 ); 765 766 OutHTML_SwTxtNode( *this, *pTxtNd ); 767 } 768 else if( pNd->IsTableNode() ) 769 { 770 OutHTML_SwTblNode( *this, *pNd->GetTableNode(), 0 ); 771 nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1; 772 } 773 else if( pNd->IsSectionNode() ) 774 { 775 OutHTML_Section( *this, *pNd->GetSectionNode() ); 776 nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1; 777 } 778 else if( pNd == &pDoc->GetNodes().GetEndOfContent() ) 779 break; 780 781 pCurPam->GetPoint()->nNode++; // Bewegen 782 sal_uInt32 nPos = pCurPam->GetPoint()->nNode.GetIndex(); 783 784 if( bShowProgress ) 785 ::SetProgressState( nPos, pDoc->GetDocShell() ); // Wie weit ? 786 787 /* sollen nur die Selectierten Bereiche gesichert werden, so 788 * duerfen nur die vollstaendigen Nodes gespeichert werde, 789 * d.H. der 1. und n. Node teilweise, der 2. bis n-1. Node 790 * vollstaendig. (vollstaendig heisst mit allen Formaten! ) 791 */ 792 bWriteAll = bSaveWriteAll || 793 nPos != pCurPam->GetMark()->nNode.GetIndex(); 794 bFirstLine = sal_False; 795 bOutFooter = sal_False; // Nach einem Node keine Fusszeile mehr 796 } 797 798 ChangeParaToken( 0 ); // MIB 8.7.97: Machen wir jetzt hier und nicht 799 // beim Aufrufer 800 OutAndSetDefList( 0 ); 801 802 } while( CopyNextPam( &pPam ) ); // bis alle PaM's bearbeitet 803 804 bWriteAll = bSaveWriteAll; // wieder auf alten Wert zurueck 805 } 806 807 808 // schreibe die StyleTabelle, algemeine Angaben,Header/Footer/Footnotes 809 static void OutBodyColor( const sal_Char *pTag, const SwFmt *pFmt, 810 SwHTMLWriter& rHWrt ) 811 { 812 const SwFmt *pRefFmt = 0; 813 814 if( rHWrt.pTemplate ) 815 pRefFmt = SwHTMLWriter::GetTemplateFmt( pFmt->GetPoolFmtId(), 816 rHWrt.pTemplate ); 817 818 const SvxColorItem *pColorItem = 0; 819 820 const SfxItemSet& rItemSet = pFmt->GetAttrSet(); 821 const SfxPoolItem *pRefItem = 0, *pItem = 0; 822 sal_Bool bItemSet = SFX_ITEM_SET == rItemSet.GetItemState( RES_CHRATR_COLOR, 823 sal_True, &pItem); 824 sal_Bool bRefItemSet = pRefFmt && 825 SFX_ITEM_SET == pRefFmt->GetAttrSet().GetItemState( RES_CHRATR_COLOR, 826 sal_True, &pRefItem); 827 if( bItemSet ) 828 { 829 // wenn das Item nur in der Vorlage des aktuellen Doks gesetzt 830 // ist oder einen anderen Wert hat, als in der HTML-Vorlage, 831 // wird es gesetzt 832 const SvxColorItem *pCItem = (const SvxColorItem*)pItem; 833 834 if( !bRefItemSet ) 835 { 836 pColorItem = pCItem; 837 } 838 else 839 { 840 Color aColor( pCItem->GetValue() ); 841 if( COL_AUTO == aColor.GetColor() ) 842 aColor.SetColor( COL_BLACK ); 843 844 Color aRefColor( ((const SvxColorItem*)pRefItem)->GetValue() ); 845 if( COL_AUTO == aRefColor.GetColor() ) 846 aRefColor.SetColor( COL_BLACK ); 847 848 if( !aColor.IsRGBEqual( aRefColor ) ) 849 pColorItem = pCItem; 850 } 851 } 852 else if( bRefItemSet ) 853 { 854 // Das Item war in der HTML-Vorlage noch gesetzt, also geben wir 855 // das Default aus 856 pColorItem = (const SvxColorItem*)&rItemSet.GetPool() 857 ->GetDefaultItem( RES_CHRATR_COLOR ); 858 } 859 860 if( pColorItem ) 861 { 862 ByteString sOut( ' ' ); 863 (sOut += pTag) += '='; 864 rHWrt.Strm() << sOut.GetBuffer(); 865 Color aColor( pColorItem->GetValue() ); 866 if( COL_AUTO == aColor.GetColor() ) 867 aColor.SetColor( COL_BLACK ); 868 HTMLOutFuncs::Out_Color( rHWrt.Strm(), aColor, rHWrt.eDestEnc ); 869 if( RES_POOLCOLL_STANDARD==pFmt->GetPoolFmtId() ) 870 rHWrt.pDfltColor = new Color( aColor ); 871 } 872 } 873 874 sal_uInt16 SwHTMLWriter::OutHeaderAttrs() 875 { 876 sal_uLong nIdx = pCurPam->GetPoint()->nNode.GetIndex(); 877 sal_uLong nEndIdx = pCurPam->GetMark()->nNode.GetIndex(); 878 879 SwTxtNode *pTxtNd = 0; 880 while( nIdx<=nEndIdx && 881 0==(pTxtNd=pDoc->GetNodes()[nIdx]->GetTxtNode()) ) 882 nIdx++; 883 884 ASSERT( pTxtNd, "Kein Text-Node gefunden" ); 885 if( !pTxtNd || !pTxtNd->HasHints() ) 886 return 0; 887 888 sal_uInt16 nAttrs = 0; 889 sal_uInt16 nCntAttr = pTxtNd->GetSwpHints().Count(); 890 xub_StrLen nOldPos = 0; 891 for( sal_uInt16 i=0; i<nCntAttr; i++ ) 892 { 893 const SwTxtAttr *pHt = pTxtNd->GetSwpHints()[i]; 894 if( !pHt->GetEnd() ) 895 { 896 xub_StrLen nPos = *pHt->GetStart(); 897 if( nPos-nOldPos > 1 || RES_TXTATR_FIELD != pHt->Which() ) 898 break; 899 900 sal_uInt16 nFldWhich = ((const SwFmtFld&)pHt->GetAttr()).GetFld() 901 ->GetTyp()->Which(); 902 if( RES_POSTITFLD!=nFldWhich && 903 RES_SCRIPTFLD!=nFldWhich ) 904 break; 905 906 OutNewLine(); 907 OutHTML_SwFmtFld( *this, pHt->GetAttr() ); 908 nOldPos = nPos; 909 nAttrs++; 910 } 911 } 912 913 return nAttrs; 914 } 915 916 const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs ) 917 { 918 ByteString sOut( OOO_STRING_SVTOOLS_HTML_doctype ); 919 (sOut += ' ') += 920 (HTML_CFG_HTML32==nExportMode ? OOO_STRING_SVTOOLS_HTML_doctype32 921 : OOO_STRING_SVTOOLS_HTML_doctype40); 922 HTMLOutFuncs::Out_AsciiTag( Strm(), sOut.GetBuffer() ); 923 924 // baue den Vorspann 925 OutNewLine(); 926 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html ); 927 928 OutNewLine(); 929 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head ); 930 931 IncIndentLevel(); // Inhalt von <HEAD> einruecken 932 933 // DokumentInfo 934 ByteString sIndent; 935 GetIndentString( sIndent ); 936 // OutNewLine(); 937 using namespace ::com::sun::star; 938 uno::Reference<document::XDocumentProperties> xDocProps; 939 SwDocShell *pDocShell(pDoc->GetDocShell()); 940 if (pDocShell) { 941 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( 942 pDocShell->GetModel(), uno::UNO_QUERY_THROW); 943 xDocProps.set(xDPS->getDocumentProperties()); 944 } 945 946 // xDocProps may be null here (when copying) 947 SfxFrameHTMLWriter::Out_DocInfo( Strm(), GetBaseURL(), xDocProps, 948 sIndent.GetBuffer(), eDestEnc, 949 &aNonConvertableCharacters ); 950 951 // Kommentare und Meta-Tags des ersten Absatzes 952 rHeaderAttrs = OutHeaderAttrs(); 953 954 OutFootEndNoteInfo(); 955 956 const SwPageDesc *pPageDesc = 0; 957 //if( !pDoc->IsHTMLMode() ) 958 //{ 959 // In Nicht-HTML-Dokumenten wird die erste gesetzte Seitenvorlage 960 // exportiert und wenn keine gesetzt ist die Standard-Vorlage 961 sal_uLong nNodeIdx = pCurPam->GetPoint()->nNode.GetIndex(); 962 963 while( nNodeIdx < pDoc->GetNodes().Count() ) 964 { 965 SwNode *pNd = pDoc->GetNodes()[ nNodeIdx ]; 966 if( pNd->IsCntntNode() ) 967 { 968 pPageDesc = ((const SwFmtPageDesc &)pNd->GetCntntNode() 969 ->GetAttr(RES_PAGEDESC)).GetPageDesc(); 970 break; 971 } 972 else if( pNd->IsTableNode() ) 973 { 974 pPageDesc = pNd->GetTableNode()->GetTable().GetFrmFmt() 975 ->GetPageDesc().GetPageDesc(); 976 break; 977 } 978 979 nNodeIdx++; 980 } 981 982 if( !pPageDesc ) 983 pPageDesc = &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 ); 984 //} 985 //else 986 //{ 987 // In HTML-Dokumenten nehmen wir immer die HTML-Vorlage 988 // pPageDesc = pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML ); 989 //} 990 991 // und nun ... das Style-Sheet!!! 992 if( bCfgOutStyles ) 993 { 994 OutStyleSheet( *pPageDesc ); 995 } 996 997 // und nun ... das BASIC und JavaScript! 998 if( pDoc->GetDocShell() ) // nur mit DocShell ist Basic moeglich 999 OutBasic(); 1000 1001 DecIndentLevel(); // Inhalt von <HEAD> einruecken 1002 OutNewLine(); 1003 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head, sal_False ); 1004 1005 // der Body wird nicht eingerueckt, weil sonst alles eingerueckt waere! 1006 OutNewLine(); 1007 sOut = '<'; 1008 sOut += OOO_STRING_SVTOOLS_HTML_body; 1009 Strm() << sOut.GetBuffer(); 1010 sOut.Erase(); 1011 1012 // language 1013 OutLanguage( eLang ); 1014 1015 // Textfarbe ausgeben, wenn sie an der Standard-Vorlage gesetzt ist 1016 // und sich geaendert hat. 1017 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_text, 1018 pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ), 1019 *this ); 1020 1021 // Farben fuer (un)besuchte Links 1022 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_link, 1023 pDoc->GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL ), 1024 *this ); 1025 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_vlink, 1026 pDoc->GetCharFmtFromPool( RES_POOLCHR_INET_VISIT ), 1027 *this ); 1028 1029 const SfxItemSet& rItemSet = pPageDesc->GetMaster().GetAttrSet(); 1030 1031 String aEmbGrfName; 1032 OutBackground( rItemSet, aEmbGrfName, sal_True ); 1033 1034 nDirection = GetHTMLDirection( rItemSet ); 1035 OutDirection( nDirection ); 1036 1037 if( bCfgOutStyles ) 1038 OutCSS1_BodyTagStyleOpt( *this, rItemSet, aEmbGrfName ); 1039 1040 // Events anhaengen 1041 if( pDoc->GetDocShell() ) // nur mit DocShell ist Basic moeglich 1042 OutBasicBodyEvents(); 1043 1044 Strm() << '>'; 1045 1046 return pPageDesc; 1047 } 1048 1049 void SwHTMLWriter::OutAnchor( const String& rName ) 1050 { 1051 ByteString sOut( '<' ); 1052 (((sOut += OOO_STRING_SVTOOLS_HTML_anchor) += ' ') += OOO_STRING_SVTOOLS_HTML_O_name) += "=\""; 1053 Strm() << sOut.GetBuffer(); 1054 HTMLOutFuncs::Out_String( Strm(), rName, eDestEnc, &aNonConvertableCharacters ) << "\">"; 1055 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_anchor, sal_False ); 1056 } 1057 1058 void SwHTMLWriter::OutBookmarks() 1059 { 1060 // hole das aktuelle Bookmark 1061 const ::sw::mark::IMark* pBookmark = NULL; 1062 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); 1063 if(nBkmkTabPos != -1) 1064 pBookmark = (pMarkAccess->getMarksBegin() + nBkmkTabPos)->get(); 1065 // Ausgabe aller Bookmarks in diesem Absatz. Die Content-Position 1066 // wird vorerst nicht beruecksichtigt! 1067 sal_uInt32 nNode = pCurPam->GetPoint()->nNode.GetIndex(); 1068 while( nBkmkTabPos != -1 && 1069 pBookmark->GetMarkPos().nNode.GetIndex() == nNode ) 1070 { 1071 // Der Bereich derBookmark wird erstam ignoriert, da er von uns 1072 // auch nicht eingelesen wird. 1073 1074 // erst die SWG spezifischen Daten: 1075 if(dynamic_cast< const ::sw::mark::IBookmark* >(pBookmark) && pBookmark->GetName().getLength() ) 1076 OutAnchor( pBookmark->GetName() ); 1077 1078 if( ++nBkmkTabPos >= pMarkAccess->getMarksCount() ) 1079 nBkmkTabPos = -1; 1080 else 1081 pBookmark = (pMarkAccess->getMarksBegin() + nBkmkTabPos)->get(); 1082 } 1083 1084 sal_uInt16 nPos; 1085 for( nPos = 0; nPos < aOutlineMarkPoss.Count() && 1086 aOutlineMarkPoss[nPos] < nNode; nPos++ ) 1087 ; 1088 1089 while( nPos < aOutlineMarkPoss.Count() && aOutlineMarkPoss[nPos] == nNode ) 1090 { 1091 String sMark( *aOutlineMarks[nPos] ); 1092 sMark.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5 1093 OutAnchor( sMark ); 1094 aOutlineMarkPoss.Remove( nPos, 1 ); 1095 aOutlineMarks.DeleteAndDestroy( nPos, 1 ); 1096 } 1097 } 1098 1099 void SwHTMLWriter::OutImplicitMark( const String& rMark, 1100 const sal_Char *pMarkType ) 1101 { 1102 if( rMark.Len() && aImplicitMarks.Count() ) 1103 { 1104 String sMark( rMark ); 1105 sMark.Append( cMarkSeperator ); 1106 sMark.AppendAscii( pMarkType ); 1107 sal_uInt16 nPos; 1108 if( aImplicitMarks.Seek_Entry( &sMark, &nPos ) ) 1109 { 1110 sMark.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5 1111 OutAnchor( sMark ); 1112 aImplicitMarks.DeleteAndDestroy( nPos, 1 ); 1113 } 1114 } 1115 } 1116 1117 void SwHTMLWriter::OutHyperlinkHRefValue( const String& rURL ) 1118 { 1119 String sURL( rURL ); 1120 xub_StrLen nPos = sURL.SearchBackward( cMarkSeperator ); 1121 if( STRING_NOTFOUND != nPos ) 1122 { 1123 String sCmp( sURL.Copy( nPos+1 ) ); 1124 sCmp.EraseAllChars(); 1125 if( sCmp.Len() ) 1126 { 1127 sCmp.ToLowerAscii(); 1128 if( sCmp.EqualsAscii( pMarkToRegion ) || 1129 sCmp.EqualsAscii( pMarkToFrame ) || 1130 sCmp.EqualsAscii( pMarkToGraphic ) || 1131 sCmp.EqualsAscii( pMarkToOLE ) || 1132 sCmp.EqualsAscii( pMarkToTable ) || 1133 sCmp.EqualsAscii( pMarkToOutline ) || 1134 sCmp.EqualsAscii( pMarkToText ) ) 1135 { 1136 sURL.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5 1137 } 1138 } 1139 } 1140 1141 sURL = URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), sURL); 1142 HTMLOutFuncs::Out_String( Strm(), sURL, eDestEnc, 1143 &aNonConvertableCharacters ); 1144 } 1145 1146 void SwHTMLWriter::OutBackground( const SvxBrushItem *pBrushItem, 1147 String& rEmbGrfNm, sal_Bool bGraphic ) 1148 { 1149 const Color &rBackColor = pBrushItem->GetColor(); 1150 /// OD 02.09.2002 #99657# 1151 /// check, if background color is not "no fill"/"auto fill", instead of 1152 /// only checking, if transparency is not set. 1153 if( rBackColor.GetColor() != COL_TRANSPARENT ) 1154 { 1155 ByteString sOut( ' ' ); 1156 (sOut += OOO_STRING_SVTOOLS_HTML_O_bgcolor) += '='; 1157 Strm() << sOut.GetBuffer(); 1158 HTMLOutFuncs::Out_Color( Strm(), rBackColor, eDestEnc); 1159 } 1160 1161 if( !bGraphic ) 1162 return; 1163 1164 const String *pLink = pBrushItem->GetGraphicLink(); 1165 1166 // embeddete Grafik -> WriteEmbedded schreiben 1167 if( !pLink ) 1168 { 1169 const Graphic* pGrf = pBrushItem->GetGraphic(); 1170 if( pGrf ) 1171 { 1172 // Grafik als (JPG-)File speichern 1173 const String* pTempFileName = GetOrigFileName(); 1174 if(pTempFileName) 1175 rEmbGrfNm = *pTempFileName; 1176 sal_uInt16 nErr = XOutBitmap::WriteGraphic( *pGrf, rEmbGrfNm, 1177 String::CreateFromAscii( "JPG" ), 1178 XOUTBMP_USE_NATIVE_IF_POSSIBLE ); 1179 if( !nErr ) // fehlerhaft, da ist nichts auszugeben 1180 { 1181 rEmbGrfNm = URIHelper::SmartRel2Abs( 1182 INetURLObject( GetBaseURL() ), rEmbGrfNm, 1183 URIHelper::GetMaybeFileHdl() ); 1184 pLink = &rEmbGrfNm; 1185 } 1186 else 1187 { 1188 nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE; 1189 } 1190 } 1191 } 1192 else 1193 { 1194 rEmbGrfNm = *pLink; 1195 if( bCfgCpyLinkedGrfs ) 1196 { 1197 CopyLocalFileToINet( rEmbGrfNm ); 1198 pLink = &rEmbGrfNm; 1199 } 1200 } 1201 1202 if( pLink ) 1203 { 1204 ByteString sOut( ' ' ); 1205 String s( URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), *pLink)); 1206 (sOut += OOO_STRING_SVTOOLS_HTML_O_background) += "=\""; 1207 Strm() << sOut.GetBuffer(); 1208 HTMLOutFuncs::Out_String( Strm(), s, eDestEnc, &aNonConvertableCharacters ) << '\"'; 1209 } 1210 } 1211 1212 void SwHTMLWriter::OutBackground( const SfxItemSet& rItemSet, 1213 String& rEmbGrfNm, sal_Bool bGraphic ) 1214 { 1215 const SfxPoolItem* pItem; 1216 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, 1217 &pItem )) 1218 { 1219 OutBackground( ((const SvxBrushItem*)pItem), rEmbGrfNm, bGraphic ); 1220 } 1221 } 1222 1223 sal_uInt16 SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript ) 1224 { 1225 sal_uInt16 nWhichId; 1226 switch( nScript ) 1227 { 1228 case CSS1_OUTMODE_CJK: 1229 nWhichId = RES_CHRATR_CJK_LANGUAGE; 1230 break; 1231 case CSS1_OUTMODE_CTL: 1232 nWhichId = RES_CHRATR_CJK_LANGUAGE; 1233 break; 1234 default: 1235 nWhichId = RES_CHRATR_LANGUAGE; 1236 break; 1237 } 1238 return nWhichId; 1239 } 1240 1241 void SwHTMLWriter::OutLanguage( LanguageType nLang ) 1242 { 1243 if( LANGUAGE_DONTKNOW != nLang ) 1244 { 1245 ByteString sOut( ' ' ); 1246 (sOut += OOO_STRING_SVTOOLS_HTML_O_lang) += "=\""; 1247 Strm() << sOut.GetBuffer(); 1248 HTMLOutFuncs::Out_String( Strm(), MsLangId::convertLanguageToIsoString(nLang), 1249 eDestEnc, &aNonConvertableCharacters ) << '"'; 1250 } 1251 } 1252 1253 sal_uInt16 SwHTMLWriter::GetHTMLDirection( const SfxItemSet& rItemSet ) const 1254 { 1255 return GetHTMLDirection( 1256 static_cast < const SvxFrameDirectionItem& >( rItemSet.Get( RES_FRAMEDIR ) ) 1257 .GetValue() ); 1258 } 1259 1260 sal_uInt16 SwHTMLWriter::GetHTMLDirection( sal_uInt16 nDir ) const 1261 { 1262 switch( nDir ) 1263 { 1264 case FRMDIR_VERT_TOP_LEFT: 1265 nDir = FRMDIR_HORI_LEFT_TOP; 1266 break; 1267 case FRMDIR_VERT_TOP_RIGHT: 1268 nDir = FRMDIR_HORI_RIGHT_TOP; 1269 break; 1270 case FRMDIR_ENVIRONMENT: 1271 nDir = nDirection; 1272 } 1273 1274 return nDir; 1275 } 1276 1277 void SwHTMLWriter::OutDirection( sal_uInt16 nDir ) 1278 { 1279 const sal_Char *pValue = 0; 1280 switch( nDir ) 1281 { 1282 case FRMDIR_HORI_LEFT_TOP: 1283 case FRMDIR_VERT_TOP_LEFT: 1284 pValue = "LTR"; 1285 break; 1286 case FRMDIR_HORI_RIGHT_TOP: 1287 case FRMDIR_VERT_TOP_RIGHT: 1288 pValue = "RTL"; 1289 break; 1290 } 1291 if( pValue != 0 ) 1292 { 1293 ByteString sOut( ' ' ); 1294 (((sOut += OOO_STRING_SVTOOLS_HTML_O_dir) += "=\"") += pValue) += '\"'; 1295 Strm() << sOut.GetBuffer(); 1296 } 1297 } 1298 1299 void SwHTMLWriter::GetIndentString( ByteString& rStr, sal_uInt16 nIncLvl ) 1300 { 1301 // etwas umstaendlich, aber wir haben nur einen Indent-String! 1302 sal_uInt16 nLevel = nIndentLvl + nIncLvl; 1303 1304 if( nLevel && nLevel <= MAX_INDENT_LEVEL) 1305 { 1306 sIndentTabs[nLevel] = 0; 1307 rStr = sIndentTabs; 1308 sIndentTabs[nLevel] = '\t'; 1309 } 1310 } 1311 1312 void SwHTMLWriter::OutNewLine( sal_Bool bCheck ) 1313 { 1314 if( !bCheck || (Strm().Tell()-nLastLFPos) > nIndentLvl ) 1315 { 1316 Strm() << sNewLine; 1317 nLastLFPos = Strm().Tell(); 1318 } 1319 1320 if( nIndentLvl && nIndentLvl <= MAX_INDENT_LEVEL) 1321 { 1322 sIndentTabs[nIndentLvl] = 0; 1323 Strm() << sIndentTabs; 1324 sIndentTabs[nIndentLvl] = '\t'; 1325 } 1326 } 1327 1328 sal_uInt16 SwHTMLWriter::GetHTMLFontSize( sal_uInt32 nHeight ) const 1329 { 1330 sal_uInt16 nSize = 1; 1331 for( sal_uInt16 i=6; i>0; i-- ) 1332 { 1333 if( nHeight > (aFontHeights[i] + aFontHeights[i-1])/2 ) 1334 { 1335 nSize = i+1; 1336 break; 1337 } 1338 } 1339 1340 return nSize; 1341 } 1342 1343 // Struktur speichert die aktuellen Daten des Writers zwischen, um 1344 // einen anderen Dokument-Teil auszugeben, wie z.B. Header/Footer 1345 HTMLSaveData::HTMLSaveData( SwHTMLWriter& rWriter, sal_uLong nStt, 1346 sal_uLong nEnd, sal_Bool bSaveNum, 1347 const SwFrmFmt *pFrmFmt ) : 1348 rWrt( rWriter ), 1349 pOldPam( rWrt.pCurPam ), 1350 pOldEnd( rWrt.GetEndPaM() ), 1351 pOldNumRuleInfo( 0 ), 1352 pOldNextNumRuleInfo( 0 ), 1353 nOldDefListLvl( rWrt.nDefListLvl ), 1354 nOldDirection( rWrt.nDirection ), 1355 bOldOutHeader( rWrt.bOutHeader ), 1356 bOldOutFooter( rWrt.bOutFooter ), 1357 bOldOutFlyFrame( rWrt.bOutFlyFrame ) 1358 { 1359 bOldWriteAll = rWrt.bWriteAll; 1360 1361 rWrt.pCurPam = rWrt.NewSwPaM( *rWrt.pDoc, nStt, nEnd ); 1362 1363 // Tabelle in Sonderbereichen erkennen 1364 if( nStt != rWrt.pCurPam->GetMark()->nNode.GetIndex() ) 1365 { 1366 const SwNode *pNd = rWrt.pDoc->GetNodes()[ nStt ]; 1367 if( pNd->IsTableNode() || pNd->IsSectionNode() ) 1368 rWrt.pCurPam->GetMark()->nNode = nStt; 1369 } 1370 1371 rWrt.SetEndPaM( rWrt.pCurPam ); 1372 rWrt.pCurPam->Exchange( ); 1373 rWrt.bWriteAll = sal_True; 1374 rWrt.nDefListLvl = 0; 1375 rWrt.bOutHeader = rWrt.bOutFooter = sal_False; 1376 1377 // Ggf. die aktuelle Numerierungs-Info merken, damit sie wieder 1378 // neu aufgenommen werden kann. Nur dann belibt auch die Numerierungs- 1379 // Info des nachsten Absatz gueltig. 1380 if( bSaveNum ) 1381 { 1382 pOldNumRuleInfo = new SwHTMLNumRuleInfo( rWrt.GetNumInfo() ); 1383 pOldNextNumRuleInfo = rWrt.GetNextNumInfo(); 1384 rWrt.SetNextNumInfo( 0 ); 1385 } 1386 else 1387 { 1388 rWrt.ClearNextNumInfo(); 1389 } 1390 1391 // Die Numerierung wird in jedem Fall unterbrochen. 1392 rWrt.GetNumInfo().Clear(); 1393 1394 if( pFrmFmt ) 1395 rWrt.nDirection = rWrt.GetHTMLDirection( pFrmFmt->GetAttrSet() ); 1396 } 1397 1398 1399 HTMLSaveData::~HTMLSaveData() 1400 { 1401 delete rWrt.pCurPam; // Pam wieder loeschen 1402 1403 rWrt.pCurPam = pOldPam; 1404 rWrt.SetEndPaM( pOldEnd ); 1405 rWrt.bWriteAll = bOldWriteAll; 1406 rWrt.nBkmkTabPos = bOldWriteAll ? rWrt.FindPos_Bkmk( *pOldPam->GetPoint() ) : -1; 1407 rWrt.nLastParaToken = 0; 1408 rWrt.nDefListLvl = nOldDefListLvl; 1409 rWrt.nDirection = nOldDirection; 1410 rWrt.bOutHeader = bOldOutHeader; 1411 rWrt.bOutFooter = bOldOutFooter; 1412 rWrt.bOutFlyFrame = bOldOutFlyFrame; 1413 1414 // Ggf. die Numerierung von vor der Section fortsetzen. Die Numerierung 1415 // des naecshten Absatz wird in jedem Fall ungueltig. 1416 if( pOldNumRuleInfo ) 1417 { 1418 rWrt.GetNumInfo().Set( *pOldNumRuleInfo ); 1419 delete pOldNumRuleInfo; 1420 rWrt.SetNextNumInfo( pOldNextNumRuleInfo ); 1421 } 1422 else 1423 { 1424 rWrt.GetNumInfo().Clear(); 1425 rWrt.ClearNextNumInfo(); 1426 } 1427 } 1428 1429 1430 void GetHTMLWriter( const String&, const String& rBaseURL, WriterRef& xRet ) 1431 { 1432 xRet = new SwHTMLWriter( rBaseURL ); 1433 } 1434 1435 1436