summaryrefslogtreecommitdiff
path: root/sc/source/filter/rtf
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/rtf')
-rw-r--r--sc/source/filter/rtf/eeimpars.cxx636
-rw-r--r--sc/source/filter/rtf/expbase.cxx107
-rw-r--r--sc/source/filter/rtf/makefile.mk59
-rw-r--r--sc/source/filter/rtf/rtfexp.cxx305
-rw-r--r--sc/source/filter/rtf/rtfimp.cxx75
-rw-r--r--sc/source/filter/rtf/rtfparse.cxx420
6 files changed, 1602 insertions, 0 deletions
diff --git a/sc/source/filter/rtf/eeimpars.cxx b/sc/source/filter/rtf/eeimpars.cxx
new file mode 100644
index 000000000000..7fb3d16c6c8d
--- /dev/null
+++ b/sc/source/filter/rtf/eeimpars.cxx
@@ -0,0 +1,636 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+//------------------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <editeng/eeitem.hxx>
+
+
+#include <editeng/adjitem.hxx>
+#include <editeng/editobj.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/langitem.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <svtools/htmlcfg.hxx>
+#include <sfx2/sfxhtml.hxx>
+#include <svtools/parhtml.hxx>
+#include <svl/zforlist.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/syslocale.hxx>
+#include <unotools/charclass.hxx>
+
+#include "eeimport.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "editutil.hxx"
+#include "stlsheet.hxx"
+#include "docpool.hxx"
+#include "attrib.hxx"
+#include "patattr.hxx"
+#include "cell.hxx"
+#include "eeparser.hxx"
+#include "drwlayer.hxx"
+#include "rangenam.hxx"
+#include "progress.hxx"
+
+#include "globstr.hrc"
+
+// in fuins1.cxx
+extern void ScLimitSizeOnDrawPage( Size& rSize, Point& rPos, const Size& rPage );
+
+//------------------------------------------------------------------------
+
+ScEEImport::ScEEImport( ScDocument* pDocP, const ScRange& rRange ) :
+ maRange( rRange ),
+ mpDoc( pDocP ),
+ mpParser( NULL ),
+ mpRowHeights( new Table )
+{
+ const ScPatternAttr* pPattern = mpDoc->GetPattern(
+ maRange.aStart.Col(), maRange.aStart.Row(), maRange.aStart.Tab() );
+ mpEngine = new ScTabEditEngine( *pPattern, mpDoc->GetEditPool() );
+ mpEngine->SetUpdateMode( FALSE );
+ mpEngine->EnableUndo( FALSE );
+}
+
+
+ScEEImport::~ScEEImport()
+{
+ // Reihenfolge wichtig, sonst knallt's irgendwann irgendwo in irgendeinem Dtor!
+ // Ist gewaehrleistet, da ScEEImport Basisklasse ist
+ delete mpEngine; // nach Parser!
+ delete mpRowHeights;
+}
+
+
+ULONG ScEEImport::Read( SvStream& rStream, const String& rBaseURL )
+{
+ ULONG nErr = mpParser->Read( rStream, rBaseURL );
+
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ mpParser->GetDimensions( nEndCol, nEndRow );
+ if ( nEndCol != 0 )
+ {
+ nEndCol += maRange.aStart.Col() - 1;
+ if ( nEndCol > MAXCOL )
+ nEndCol = MAXCOL;
+ }
+ else
+ nEndCol = maRange.aStart.Col();
+ if ( nEndRow != 0 )
+ {
+ nEndRow += maRange.aStart.Row() - 1;
+ if ( nEndRow > MAXROW )
+ nEndRow = MAXROW;
+ }
+ else
+ nEndRow = maRange.aStart.Row();
+ maRange.aEnd.Set( nEndCol, nEndRow, maRange.aStart.Tab() );
+
+ return nErr;
+}
+
+
+void ScEEImport::WriteToDocument( BOOL bSizeColsRows, double nOutputFactor, SvNumberFormatter* pFormatter, bool bConvertDate )
+{
+ ScProgress* pProgress = new ScProgress( mpDoc->GetDocumentShell(),
+ ScGlobal::GetRscString( STR_LOAD_DOC ), mpParser->Count() );
+ ULONG nProgress = 0;
+
+ SCCOL nStartCol, nEndCol;
+ SCROW nStartRow, nEndRow;
+ SCTAB nTab;
+ SCROW nOverlapRowMax, nLastMergedRow;
+ SCCOL nMergeColAdd;
+ nStartCol = maRange.aStart.Col();
+ nStartRow = maRange.aStart.Row();
+ nTab = maRange.aStart.Tab();
+ nEndCol = maRange.aEnd.Col();
+ nEndRow = maRange.aEnd.Row();
+ nOverlapRowMax = 0;
+ nMergeColAdd = 0;
+ nLastMergedRow = SCROW_MAX;
+ BOOL bHasGraphics = FALSE;
+ ScEEParseEntry* pE;
+ if (!pFormatter)
+ pFormatter = mpDoc->GetFormatTable();
+ bool bNumbersEnglishUS = false;
+ if (pFormatter->GetLanguage() == LANGUAGE_SYSTEM)
+ {
+ // Automatic language option selected. Check for the global 'use US English' option.
+ SvxHtmlOptions aOpt;
+ bNumbersEnglishUS = aOpt.IsNumbersEnglishUS();
+ }
+ ScDocumentPool* pDocPool = mpDoc->GetPool();
+ ScRangeName* pRangeNames = mpDoc->GetRangeName();
+ for ( pE = mpParser->First(); pE; pE = mpParser->Next() )
+ {
+ SCROW nRow = nStartRow + pE->nRow;
+ if ( nRow != nLastMergedRow )
+ nMergeColAdd = 0;
+ SCCOL nCol = nStartCol + pE->nCol + nMergeColAdd;
+ // RowMerge feststellen, pures ColMerge und ColMerge der ersten
+ // MergeRow bereits beim parsen
+ if ( nRow <= nOverlapRowMax )
+ {
+ while ( nCol <= MAXCOL && mpDoc->HasAttrib( nCol, nRow, nTab,
+ nCol, nRow, nTab, HASATTR_OVERLAPPED ) )
+ {
+ nCol++;
+ nMergeColAdd++;
+ }
+ nLastMergedRow = nRow;
+ }
+ // fuer zweiten Durchlauf eintragen
+ pE->nCol = nCol;
+ pE->nRow = nRow;
+ if ( ValidCol(nCol) && ValidRow(nRow) )
+ {
+ SfxItemSet aSet = mpEngine->GetAttribs( pE->aSel );
+ // Default raus, wir setzen selber links/rechts je nachdem ob Text
+ // oder Zahl; EditView.GetAttribs liefert immer kompletten Set
+ // mit Defaults aufgefuellt
+ const SfxPoolItem& rItem = aSet.Get( EE_PARA_JUST );
+ if ( ((const SvxAdjustItem&)rItem).GetAdjust() == SVX_ADJUST_LEFT )
+ aSet.ClearItem( EE_PARA_JUST );
+
+ // Testen, ob einfacher String ohne gemischte Attribute
+ BOOL bSimple = ( pE->aSel.nStartPara == pE->aSel.nEndPara );
+ for (USHORT nId = EE_CHAR_START; nId <= EE_CHAR_END && bSimple; nId++)
+ {
+ const SfxPoolItem* pItem = 0;
+ SfxItemState eState = aSet.GetItemState( nId, TRUE, &pItem );
+ if (eState == SFX_ITEM_DONTCARE)
+ bSimple = FALSE;
+ else if (eState == SFX_ITEM_SET)
+ {
+ if ( nId == EE_CHAR_ESCAPEMENT ) // Hoch-/Tiefstellen immer ueber EE
+ {
+ if ( (SvxEscapement)((const SvxEscapementItem*)pItem)->GetEnumValue()
+ != SVX_ESCAPEMENT_OFF )
+ bSimple = FALSE;
+ }
+ }
+ }
+ if ( bSimple )
+ { // Feldbefehle enthalten?
+ SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, FALSE );
+ if ( eFieldState == SFX_ITEM_DONTCARE || eFieldState == SFX_ITEM_SET )
+ bSimple = FALSE;
+ }
+
+ // HTML
+ String aValStr, aNumStr;
+ double fVal;
+ sal_uInt32 nNumForm = 0;
+ LanguageType eNumLang = LANGUAGE_NONE;
+ if ( pE->pNumStr )
+ { // SDNUM muss sein wenn SDVAL
+ aNumStr = *pE->pNumStr;
+ if ( pE->pValStr )
+ aValStr = *pE->pValStr;
+ fVal = SfxHTMLParser::GetTableDataOptionsValNum(
+ nNumForm, eNumLang, aValStr, aNumStr, *pFormatter );
+ }
+
+ // Attribute setzen
+ ScPatternAttr aAttr( pDocPool );
+ aAttr.GetFromEditItemSet( &aSet );
+ SfxItemSet& rSet = aAttr.GetItemSet();
+ if ( aNumStr.Len() )
+ {
+ rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumForm ) );
+ rSet.Put( SvxLanguageItem( eNumLang, ATTR_LANGUAGE_FORMAT ) );
+ }
+ const SfxItemSet& rESet = pE->aItemSet;
+ if ( rESet.Count() )
+ {
+ const SfxPoolItem* pItem;
+ if ( rESet.GetItemState( ATTR_BACKGROUND, FALSE, &pItem) == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ if ( rESet.GetItemState( ATTR_BORDER, FALSE, &pItem) == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ if ( rESet.GetItemState( ATTR_SHADOW, FALSE, &pItem) == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ // HTML
+ if ( rESet.GetItemState( ATTR_HOR_JUSTIFY, FALSE, &pItem) == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ if ( rESet.GetItemState( ATTR_VER_JUSTIFY, FALSE, &pItem) == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ if ( rESet.GetItemState( ATTR_LINEBREAK, FALSE, &pItem) == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ if ( rESet.GetItemState( ATTR_FONT_COLOR, FALSE, &pItem) == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ if ( rESet.GetItemState( ATTR_FONT_UNDERLINE, FALSE, &pItem) == SFX_ITEM_SET )
+ rSet.Put( *pItem );
+ // HTML LATIN/CJK/CTL script type dependent
+ const SfxPoolItem* pFont;
+ if ( rESet.GetItemState( ATTR_FONT, FALSE, &pFont) != SFX_ITEM_SET )
+ pFont = 0;
+ const SfxPoolItem* pHeight;
+ if ( rESet.GetItemState( ATTR_FONT_HEIGHT, FALSE, &pHeight) != SFX_ITEM_SET )
+ pHeight = 0;
+ const SfxPoolItem* pWeight;
+ if ( rESet.GetItemState( ATTR_FONT_WEIGHT, FALSE, &pWeight) != SFX_ITEM_SET )
+ pWeight = 0;
+ const SfxPoolItem* pPosture;
+ if ( rESet.GetItemState( ATTR_FONT_POSTURE, FALSE, &pPosture) != SFX_ITEM_SET )
+ pPosture = 0;
+ if ( pFont || pHeight || pWeight || pPosture )
+ {
+ String aStr( mpEngine->GetText( pE->aSel ) );
+ BYTE nScriptType = mpDoc->GetStringScriptType( aStr );
+ const BYTE nScripts[3] = { SCRIPTTYPE_LATIN,
+ SCRIPTTYPE_ASIAN, SCRIPTTYPE_COMPLEX };
+ for ( BYTE i=0; i<3; ++i )
+ {
+ if ( nScriptType & nScripts[i] )
+ {
+ if ( pFont )
+ rSet.Put( *pFont, ScGlobal::GetScriptedWhichID(
+ nScripts[i], ATTR_FONT ));
+ if ( pHeight )
+ rSet.Put( *pHeight, ScGlobal::GetScriptedWhichID(
+ nScripts[i], ATTR_FONT_HEIGHT ));
+ if ( pWeight )
+ rSet.Put( *pWeight, ScGlobal::GetScriptedWhichID(
+ nScripts[i], ATTR_FONT_WEIGHT ));
+ if ( pPosture )
+ rSet.Put( *pPosture, ScGlobal::GetScriptedWhichID(
+ nScripts[i], ATTR_FONT_POSTURE ));
+ }
+ }
+ }
+ }
+ if ( pE->nColOverlap > 1 || pE->nRowOverlap > 1 )
+ { // merged cells, mit SfxItemSet Put schneller als mit
+ // nachtraeglichem ScDocument DoMerge
+ ScMergeAttr aMerge( pE->nColOverlap, pE->nRowOverlap );
+ rSet.Put( aMerge );
+ SCROW nRO = 0;
+ if ( pE->nColOverlap > 1 )
+ mpDoc->ApplyFlagsTab( nCol+1, nRow,
+ nCol + pE->nColOverlap - 1, nRow, nTab,
+ SC_MF_HOR );
+ if ( pE->nRowOverlap > 1 )
+ {
+ nRO = nRow + pE->nRowOverlap - 1;
+ mpDoc->ApplyFlagsTab( nCol, nRow+1,
+ nCol, nRO , nTab,
+ SC_MF_VER );
+ if ( nRO > nOverlapRowMax )
+ nOverlapRowMax = nRO;
+ }
+ if ( pE->nColOverlap > 1 && pE->nRowOverlap > 1 )
+ mpDoc->ApplyFlagsTab( nCol+1, nRow+1,
+ nCol + pE->nColOverlap - 1, nRO, nTab,
+ SC_MF_HOR | SC_MF_VER );
+ }
+ const ScStyleSheet* pStyleSheet =
+ mpDoc->GetPattern( nCol, nRow, nTab )->GetStyleSheet();
+ aAttr.SetStyleSheet( (ScStyleSheet*)pStyleSheet );
+ mpDoc->SetPattern( nCol, nRow, nTab, aAttr, TRUE );
+
+ // Daten eintragen
+ if (bSimple)
+ {
+ if ( aValStr.Len() )
+ mpDoc->SetValue( nCol, nRow, nTab, fVal );
+ else if ( !pE->aSel.HasRange() )
+ {
+ // maybe ALT text of IMG or similar
+ mpDoc->SetString( nCol, nRow, nTab, pE->aAltText, pFormatter );
+ // wenn SelRange komplett leer kann nachfolgender Text im gleichen Absatz liegen!
+ }
+ else
+ {
+ String aStr;
+ if( pE->bEntirePara )
+ {
+ aStr = mpEngine->GetText( pE->aSel.nStartPara );
+ }
+ else
+ {
+ aStr = mpEngine->GetText( pE->aSel );
+ aStr.EraseLeadingAndTrailingChars();
+ }
+
+ // TODO: RTF import should follow the language tag,
+ // currently this follows the HTML options for both, HTML
+ // and RTF.
+ bool bEnUsRecognized = false;
+ if (bNumbersEnglishUS)
+ {
+ pFormatter->ChangeIntl( LANGUAGE_ENGLISH_US);
+ sal_uInt32 nIndex = pFormatter->GetStandardIndex( LANGUAGE_ENGLISH_US);
+ double fEnVal = 0.0;
+ if (pFormatter->IsNumberFormat( aStr, nIndex, fEnVal))
+ {
+ bEnUsRecognized = true;
+ sal_uInt32 nNewIndex =
+ pFormatter->GetFormatForLanguageIfBuiltIn(
+ nIndex, LANGUAGE_SYSTEM);
+ DBG_ASSERT( nNewIndex != nIndex, "ScEEImport::WriteToDocument: NumbersEnglishUS not a built-in format?");
+ pFormatter->GetInputLineString( fEnVal, nNewIndex, aStr);
+ }
+ pFormatter->ChangeIntl( LANGUAGE_SYSTEM);
+ }
+
+ // #105460#, #i4180# String cells can't contain tabs or linebreaks
+ // -> replace with spaces
+ aStr.SearchAndReplaceAll( (sal_Unicode)'\t', (sal_Unicode)' ' );
+ aStr.SearchAndReplaceAll( (sal_Unicode)'\n', (sal_Unicode)' ' );
+
+ if (bNumbersEnglishUS && !bEnUsRecognized)
+ mpDoc->PutCell( nCol, nRow, nTab, new ScStringCell( aStr));
+ else
+ mpDoc->SetString( nCol, nRow, nTab, aStr, pFormatter, bConvertDate );
+ }
+ }
+ else
+ {
+ EditTextObject* pObject = mpEngine->CreateTextObject( pE->aSel );
+ mpDoc->PutCell( nCol, nRow, nTab, new ScEditCell( pObject,
+ mpDoc, mpEngine->GetEditTextObjectPool() ) );
+ delete pObject;
+ }
+ if ( pE->pImageList )
+ bHasGraphics |= GraphicSize( nCol, nRow, nTab, pE );
+ if ( pE->pName )
+ { // Anchor Name => RangeName
+ USHORT nIndex;
+ if ( !pRangeNames->SearchName( *pE->pName, nIndex ) )
+ {
+ ScRangeData* pData = new ScRangeData( mpDoc, *pE->pName,
+ ScAddress( nCol, nRow, nTab ) );
+ pRangeNames->Insert( pData );
+ }
+ }
+ }
+ pProgress->SetStateOnPercent( ++nProgress );
+ }
+ if ( bSizeColsRows )
+ {
+ // Spaltenbreiten
+ Table* pColWidths = mpParser->GetColWidths();
+ if ( pColWidths->Count() )
+ {
+ nProgress = 0;
+ pProgress->SetState( nProgress, nEndCol - nStartCol + 1 );
+ for ( SCCOL nCol = nStartCol; nCol <= nEndCol; nCol++ )
+ {
+ USHORT nWidth = (USHORT)(ULONG) pColWidths->Get( nCol );
+ if ( nWidth )
+ mpDoc->SetColWidth( nCol, nTab, nWidth );
+ pProgress->SetState( ++nProgress );
+ }
+ }
+ DELETEZ( pProgress ); // SetOptimalHeight hat seinen eigenen ProgressBar
+ // Zeilenhoehen anpassen, Basis 100% Zoom
+ Fraction aZoom( 1, 1 );
+ double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom
+ / nOutputFactor; // Faktor ist Drucker zu Bildschirm
+ double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
+ VirtualDevice aVirtDev;
+ mpDoc->SetOptimalHeight( 0, nEndRow, 0,
+ static_cast< USHORT >( ScGlobal::nLastRowHeightExtra ), &aVirtDev,
+ nPPTX, nPPTY, aZoom, aZoom, FALSE );
+ if ( mpRowHeights->Count() )
+ {
+ for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow++ )
+ {
+ USHORT nHeight = (USHORT)(ULONG) mpRowHeights->Get( nRow );
+ if ( nHeight > mpDoc->GetRowHeight( nRow, nTab ) )
+ mpDoc->SetRowHeight( nRow, nTab, nHeight );
+ }
+ }
+ }
+ if ( bHasGraphics )
+ { // Grafiken einfuegen
+ for ( pE = mpParser->First(); pE; pE = mpParser->Next() )
+ {
+ if ( pE->pImageList )
+ {
+ SCCOL nCol = pE->nCol;
+ SCROW nRow = pE->nRow;
+ if ( ValidCol(nCol) && ValidRow(nRow) )
+ InsertGraphic( nCol, nRow, nTab, pE );
+ }
+ }
+ }
+ if ( pProgress )
+ delete pProgress;
+}
+
+
+BOOL ScEEImport::GraphicSize( SCCOL nCol, SCROW nRow, SCTAB /*nTab*/,
+ ScEEParseEntry* pE )
+{
+ ScHTMLImageList* pIL = pE->pImageList;
+ if ( !pIL || !pIL->Count() )
+ return FALSE;
+ BOOL bHasGraphics = FALSE;
+ OutputDevice* pDefaultDev = Application::GetDefaultDevice();
+ long nWidth, nHeight;
+ nWidth = nHeight = 0;
+ sal_Char nDir = nHorizontal;
+ for ( ScHTMLImage* pI = pIL->First(); pI; pI = pIL->Next() )
+ {
+ if ( pI->pGraphic )
+ bHasGraphics = TRUE;
+ Size aSizePix = pI->aSize;
+ aSizePix.Width() += 2 * pI->aSpace.X();
+ aSizePix.Height() += 2 * pI->aSpace.Y();
+ Size aLogicSize = pDefaultDev->PixelToLogic( aSizePix, MapMode( MAP_TWIP ) );
+ if ( nDir & nHorizontal )
+ nWidth += aLogicSize.Width();
+ else if ( nWidth < aLogicSize.Width() )
+ nWidth = aLogicSize.Width();
+ if ( nDir & nVertical )
+ nHeight += aLogicSize.Height();
+ else if ( nHeight < aLogicSize.Height() )
+ nHeight = aLogicSize.Height();
+ nDir = pI->nDir;
+ }
+ // Spaltenbreiten
+ Table* pColWidths = mpParser->GetColWidths();
+ long nThisWidth = (long) pColWidths->Get( nCol );
+ long nColWidths = nThisWidth;
+ SCCOL nColSpanCol = nCol + pE->nColOverlap;
+ for ( SCCOL nC = nCol + 1; nC < nColSpanCol; nC++ )
+ {
+ nColWidths += (long) pColWidths->Get( nC );
+ }
+ if ( nWidth > nColWidths )
+ { // Differenz nur in der ersten Spalte eintragen
+ if ( nThisWidth )
+ pColWidths->Replace( nCol, (void*)(nWidth - nColWidths + nThisWidth) );
+ else
+ pColWidths->Insert( nCol, (void*)(nWidth - nColWidths) );
+ }
+ // Zeilenhoehen, Differenz auf alle betroffenen Zeilen verteilen
+ SCROW nRowSpan = pE->nRowOverlap;
+ nHeight /= nRowSpan;
+ if ( nHeight == 0 )
+ nHeight = 1; // fuer eindeutigen Vergleich
+ for ( SCROW nR = nRow; nR < nRow + nRowSpan; nR++ )
+ {
+ long nRowHeight = (long) mpRowHeights->Get( nR );
+ if ( nHeight > nRowHeight )
+ {
+ if ( nRowHeight )
+ mpRowHeights->Replace( nR, (void*)nHeight );
+ else
+ mpRowHeights->Insert( nR, (void*)nHeight );
+ }
+ }
+ return bHasGraphics;
+}
+
+
+void ScEEImport::InsertGraphic( SCCOL nCol, SCROW nRow, SCTAB nTab,
+ ScEEParseEntry* pE )
+{
+ ScHTMLImageList* pIL = pE->pImageList;
+ if ( !pIL || !pIL->Count() )
+ return ;
+ ScDrawLayer* pModel = mpDoc->GetDrawLayer();
+ if (!pModel)
+ {
+ mpDoc->InitDrawLayer();
+ pModel = mpDoc->GetDrawLayer();
+ }
+ SdrPage* pPage = pModel->GetPage( static_cast<sal_uInt16>(nTab) );
+ OutputDevice* pDefaultDev = Application::GetDefaultDevice();
+
+ Point aCellInsertPos(
+ (long)((double) mpDoc->GetColOffset( nCol, nTab ) * HMM_PER_TWIPS),
+ (long)((double) mpDoc->GetRowOffset( nRow, nTab ) * HMM_PER_TWIPS) );
+
+ Point aInsertPos( aCellInsertPos );
+ Point aSpace;
+ Size aLogicSize;
+ sal_Char nDir = nHorizontal;
+ for ( ScHTMLImage* pI = pIL->First(); pI; pI = pIL->Next() )
+ {
+ if ( nDir & nHorizontal )
+ { // horizontal
+ aInsertPos.X() += aLogicSize.Width();
+ aInsertPos.X() += aSpace.X();
+ aInsertPos.Y() = aCellInsertPos.Y();
+ }
+ else
+ { // vertikal
+ aInsertPos.X() = aCellInsertPos.X();
+ aInsertPos.Y() += aLogicSize.Height();
+ aInsertPos.Y() += aSpace.Y();
+ }
+ // Offset des Spacings drauf
+ aSpace = pDefaultDev->PixelToLogic( pI->aSpace, MapMode( MAP_100TH_MM ) );
+ aInsertPos += aSpace;
+
+ Size aSizePix = pI->aSize;
+ aLogicSize = pDefaultDev->PixelToLogic( aSizePix, MapMode( MAP_100TH_MM ) );
+ // Groesse begrenzen
+ ::ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
+
+ if ( pI->pGraphic )
+ {
+ Rectangle aRect ( aInsertPos, aLogicSize );
+ SdrGrafObj* pObj = new SdrGrafObj( *pI->pGraphic, aRect );
+ // #118522# calling SetGraphicLink here doesn't work
+ pObj->SetName( pI->aURL );
+
+ pPage->InsertObject( pObj );
+
+ // #118522# SetGraphicLink has to be used after inserting the object,
+ // otherwise an empty graphic is swapped in and the contact stuff crashes.
+ // See #i37444#.
+ pObj->SetGraphicLink( pI->aURL, pI->aFilterName );
+
+ pObj->SetLogicRect( aRect ); // erst nach InsertObject !!!
+ }
+ nDir = pI->nDir;
+ }
+}
+
+
+ScEEParser::ScEEParser( EditEngine* pEditP ) :
+ pEdit( pEditP ),
+ pPool( EditEngine::CreatePool() ),
+ pDocPool( new ScDocumentPool ),
+ pList( new ScEEParseList ),
+ pColWidths( new Table ),
+ nLastToken(0),
+ nColCnt(0),
+ nRowCnt(0),
+ nColMax(0),
+ nRowMax(0)
+{
+ // pPool wird spaeter bei RTFIMP_START dem SvxRTFParser untergejubelt
+ pPool->SetSecondaryPool( pDocPool );
+ pPool->FreezeIdRanges();
+ NewActEntry( NULL );
+}
+
+
+ScEEParser::~ScEEParser()
+{
+ delete pActEntry;
+ delete pColWidths;
+ for ( ScEEParseEntry* pE = pList->First(); pE; pE = pList->Next() )
+ delete pE;
+ delete pList;
+
+ // Pool erst loeschen nachdem die Listen geloescht wurden
+ pPool->SetSecondaryPool( NULL );
+ SfxItemPool::Free(pDocPool);
+ SfxItemPool::Free(pPool);
+}
+
+
+void ScEEParser::NewActEntry( ScEEParseEntry* pE )
+{ // neuer freifliegender pActEntry
+ pActEntry = new ScEEParseEntry( pPool );
+ pActEntry->aSel.nStartPara = (pE ? pE->aSel.nEndPara + 1 : 0);
+ pActEntry->aSel.nStartPos = 0;
+}
+
+
+
+
diff --git a/sc/source/filter/rtf/expbase.cxx b/sc/source/filter/rtf/expbase.cxx
new file mode 100644
index 000000000000..cd3f30ef9c9f
--- /dev/null
+++ b/sc/source/filter/rtf/expbase.cxx
@@ -0,0 +1,107 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+
+#include "expbase.hxx"
+#include "document.hxx"
+#include "editutil.hxx"
+
+
+//------------------------------------------------------------------
+
+#if defined(UNX)
+const sal_Char __FAR_DATA ScExportBase::sNewLine = '\012';
+#else
+const sal_Char __FAR_DATA ScExportBase::sNewLine[] = "\015\012";
+#endif
+
+
+ScExportBase::ScExportBase( SvStream& rStrmP, ScDocument* pDocP,
+ const ScRange& rRangeP )
+ :
+ rStrm( rStrmP ),
+ aRange( rRangeP ),
+ pDoc( pDocP ),
+ pFormatter( pDocP->GetFormatTable() ),
+ pEditEngine( NULL )
+{
+}
+
+
+ScExportBase::~ScExportBase()
+{
+ delete pEditEngine;
+}
+
+
+BOOL ScExportBase::GetDataArea( SCTAB nTab, SCCOL& nStartCol,
+ SCROW& nStartRow, SCCOL& nEndCol, SCROW& nEndRow ) const
+{
+ pDoc->GetDataStart( nTab, nStartCol, nStartRow );
+ pDoc->GetPrintArea( nTab, nEndCol, nEndRow, TRUE );
+ return TrimDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
+}
+
+
+BOOL ScExportBase::TrimDataArea( SCTAB nTab, SCCOL& nStartCol,
+ SCROW& nStartRow, SCCOL& nEndCol, SCROW& nEndRow ) const
+{
+ SCCOL nLastCol;
+ while ( nStartCol <= nEndCol && pDoc->ColHidden(nStartCol, nTab, nLastCol))
+ ++nStartCol;
+ while ( nStartCol <= nEndCol && pDoc->ColHidden(nEndCol, nTab, nLastCol))
+ --nEndCol;
+ nStartRow = pDoc->FirstVisibleRow(nStartRow, nEndRow, nTab);
+ nEndRow = pDoc->LastVisibleRow(nStartRow, nEndRow, nTab);
+ return nStartCol <= nEndCol && nStartRow <= nEndRow && nEndRow !=
+ ::std::numeric_limits<SCROW>::max();
+}
+
+
+BOOL ScExportBase::IsEmptyTable( SCTAB nTab ) const
+{
+ if ( !pDoc->HasTable( nTab ) || !pDoc->IsVisible( nTab ) )
+ return TRUE;
+ SCCOL nStartCol, nEndCol;
+ SCROW nStartRow, nEndRow;
+ return !GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
+}
+
+
+ScFieldEditEngine& ScExportBase::GetEditEngine() const
+{
+ if ( !pEditEngine )
+ ((ScExportBase*)this)->pEditEngine = new ScFieldEditEngine( pDoc->GetEditPool() );
+ return *pEditEngine;
+}
+
+
diff --git a/sc/source/filter/rtf/makefile.mk b/sc/source/filter/rtf/makefile.mk
new file mode 100644
index 000000000000..a680751de620
--- /dev/null
+++ b/sc/source/filter/rtf/makefile.mk
@@ -0,0 +1,59 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=sc
+TARGET=rtf
+
+AUTOSEG=true
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=filt_pch
+PROJECTPCHSOURCE=..\pch\filt_pch
+
+VISIBILITY_HIDDEN=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : scpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sc.mk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/eeimpars.obj \
+ $(SLO)$/expbase.obj \
+ $(SLO)$/rtfexp.obj \
+ $(SLO)$/rtfimp.obj \
+ $(SLO)$/rtfparse.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sc/source/filter/rtf/rtfexp.cxx b/sc/source/filter/rtf/rtfexp.cxx
new file mode 100644
index 000000000000..c817fc2844eb
--- /dev/null
+++ b/sc/source/filter/rtf/rtfexp.cxx
@@ -0,0 +1,305 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+#include "scitems.hxx"
+#include <editeng/eeitem.hxx>
+
+
+#include <svx/algitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <svl/style.hxx>
+#include <svtools/rtfout.hxx>
+#include <svtools/rtfkeywd.hxx>
+
+#include "rtfexp.hxx"
+#include "filter.hxx"
+#include "document.hxx"
+#include "patattr.hxx"
+#include "attrib.hxx"
+#include "cell.hxx"
+#include "cellform.hxx"
+#include "editutil.hxx"
+#include "stlpool.hxx"
+#include "ftools.hxx"
+
+//------------------------------------------------------------------
+
+FltError ScFormatFilterPluginImpl::ScExportRTF( SvStream& rStrm, ScDocument* pDoc,
+ const ScRange& rRange, const CharSet /*eNach*/ )
+{
+ ScRTFExport aEx( rStrm, pDoc, rRange );
+ return aEx.Write();
+}
+
+
+ScRTFExport::ScRTFExport( SvStream& rStrmP, ScDocument* pDocP, const ScRange& rRangeP )
+ :
+ ScExportBase( rStrmP, pDocP, rRangeP ),
+ pCellX( new ULONG[ MAXCOL+2 ] )
+{
+}
+
+
+ScRTFExport::~ScRTFExport()
+{
+ delete [] pCellX;
+}
+
+
+ULONG ScRTFExport::Write()
+{
+ rStrm << '{' << OOO_STRING_SVTOOLS_RTF_RTF;
+ rStrm << OOO_STRING_SVTOOLS_RTF_ANSI << sNewLine;
+
+#if 0
+// das ist noch nicht ausgegoren
+/*
+ SfxStyleSheetBasePool* pStylePool = pDoc->GetStyleSheetPool();
+ SfxStyleSheetBase* pStyleSheet = NULL;
+ DBG_ASSERT( pStylePool, "StylePool not found! :-(" );
+ pStylePool->SetSearchMask( SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_ALL );
+ pStyleSheet = pStylePool->Find( STRING_STANDARD, SFX_STYLE_FAMILY_PARA );
+ DBG_ASSERT( pStyleSheet, "ParaStyle not found! :-(" );
+ const SfxItemSet& rSetPara = pStyleSheet->GetItemSet();
+
+ // fonttbl
+ String aFontFamilyName(
+ ((const SvxFontItem&)(rSetPara.Get( ATTR_FONT ))).GetFamilyName() );
+ rStrm << OOO_STRING_SVTOOLS_RTF_DEFF << '0'
+ << '{' << OOO_STRING_SVTOOLS_RTF_FONTTBL
+ << '{' << OOO_STRING_SVTOOLS_RTF_F << '0' << OOO_STRING_SVTOOLS_RTF_FNIL << ' ' << aFontFamilyName.GetStr() << ";}"
+ << '}' << sNewLine;
+
+ // hier kaeme die colortbl
+
+ // stylesheet
+ UINT32 nFontHeight =
+ ((const SvxFontHeightItem&)(rSetPara.Get( ATTR_FONT_HEIGHT ))).GetHeight();
+ rStrm << '{' << OOO_STRING_SVTOOLS_RTF_STYLESHEET
+ << '{' << OOO_STRING_SVTOOLS_RTF_FS << String( UINT32(nFontHeight / TWIPS_PER_POINT) ).GetStr()
+ << ' ' << pStyleSheet->GetName().GetStr() << ";}"
+ << '}' << sNewLine;
+*/
+#endif
+
+ // Daten
+ for ( SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); nTab++ )
+ {
+ if ( nTab > aRange.aStart.Tab() )
+ rStrm << OOO_STRING_SVTOOLS_RTF_PAR;
+ WriteTab( nTab );
+ }
+
+ rStrm << '}' << sNewLine;
+ return rStrm.GetError();
+}
+
+
+void ScRTFExport::WriteTab( SCTAB nTab )
+{
+ rStrm << '{' << sNewLine;
+ if ( pDoc->HasTable( nTab ) )
+ {
+ memset( &pCellX[0], 0, (MAXCOL+2) * sizeof(ULONG) );
+ SCCOL nCol;
+ SCCOL nEndCol = aRange.aEnd.Col();
+ for ( nCol = aRange.aStart.Col(); nCol <= nEndCol; nCol++ )
+ {
+ pCellX[nCol+1] = pCellX[nCol] + pDoc->GetColWidth( nCol, nTab );
+ }
+
+ SCROW nEndRow = aRange.aEnd.Row();
+ for ( SCROW nRow = aRange.aStart.Row(); nRow <= nEndRow; nRow++ )
+ {
+ WriteRow( nTab, nRow );
+ }
+ }
+ rStrm << '}' << sNewLine;
+}
+
+
+void ScRTFExport::WriteRow( SCTAB nTab, SCROW nRow )
+{
+ rStrm << OOO_STRING_SVTOOLS_RTF_TROWD << OOO_STRING_SVTOOLS_RTF_TRGAPH << "30" << OOO_STRING_SVTOOLS_RTF_TRLEFT << "-30";
+ rStrm << OOO_STRING_SVTOOLS_RTF_TRRH << ByteString::CreateFromInt32( pDoc->GetRowHeight( nRow, nTab ) ).GetBuffer();
+ SCCOL nCol;
+ SCCOL nEndCol = aRange.aEnd.Col();
+ for ( nCol = aRange.aStart.Col(); nCol <= nEndCol; nCol++ )
+ {
+ const ScPatternAttr* pAttr = pDoc->GetPattern( nCol, nRow, nTab );
+ const ScMergeAttr& rMergeAttr = (const ScMergeAttr&) pAttr->GetItem( ATTR_MERGE );
+ const SvxVerJustifyItem& rVerJustifyItem= (const SvxVerJustifyItem&)pAttr->GetItem( ATTR_VER_JUSTIFY );
+
+ const sal_Char* pChar;
+
+ if ( rMergeAttr.GetColMerge() != 0 )
+ rStrm << OOO_STRING_SVTOOLS_RTF_CLMGF;
+ else
+ {
+ const ScMergeFlagAttr& rMergeFlagAttr = (const ScMergeFlagAttr&) pAttr->GetItem( ATTR_MERGE_FLAG );
+ if ( rMergeFlagAttr.IsHorOverlapped() )
+ rStrm << OOO_STRING_SVTOOLS_RTF_CLMRG;
+ }
+
+ switch( rVerJustifyItem.GetValue() )
+ {
+ case SVX_VER_JUSTIFY_TOP: pChar = OOO_STRING_SVTOOLS_RTF_CLVERTALT; break;
+ case SVX_VER_JUSTIFY_CENTER: pChar = OOO_STRING_SVTOOLS_RTF_CLVERTALC; break;
+ case SVX_VER_JUSTIFY_BOTTOM: pChar = OOO_STRING_SVTOOLS_RTF_CLVERTALB; break;
+ case SVX_VER_JUSTIFY_STANDARD: pChar = OOO_STRING_SVTOOLS_RTF_CLVERTALB; break; //! Bottom
+ default: pChar = NULL; break;
+ }
+ if ( pChar )
+ rStrm << pChar;
+
+ rStrm << OOO_STRING_SVTOOLS_RTF_CELLX << ByteString::CreateFromInt32( pCellX[nCol+1] ).GetBuffer();
+ if ( (nCol & 0x0F) == 0x0F )
+ rStrm << sNewLine; // Zeilen nicht zu lang werden lassen
+ }
+ rStrm << OOO_STRING_SVTOOLS_RTF_PARD << OOO_STRING_SVTOOLS_RTF_PLAIN << OOO_STRING_SVTOOLS_RTF_INTBL << sNewLine;
+
+ ULONG nStrmPos = rStrm.Tell();
+ for ( nCol = aRange.aStart.Col(); nCol <= nEndCol; nCol++ )
+ {
+ WriteCell( nTab, nRow, nCol );
+ if ( rStrm.Tell() - nStrmPos > 255 )
+ { // Zeilen nicht zu lang werden lassen
+ rStrm << sNewLine;
+ nStrmPos = rStrm.Tell();
+ }
+ }
+ rStrm << OOO_STRING_SVTOOLS_RTF_ROW << sNewLine;
+}
+
+
+void ScRTFExport::WriteCell( SCTAB nTab, SCROW nRow, SCCOL nCol )
+{
+ const ScPatternAttr* pAttr = pDoc->GetPattern( nCol, nRow, nTab );
+
+ const ScMergeFlagAttr& rMergeFlagAttr = (const ScMergeFlagAttr&) pAttr->GetItem( ATTR_MERGE_FLAG );
+ if ( rMergeFlagAttr.IsHorOverlapped() )
+ {
+ rStrm << OOO_STRING_SVTOOLS_RTF_CELL;
+ return ;
+ }
+
+ ScBaseCell* pCell;
+ pDoc->GetCell( nCol, nRow, nTab, pCell );
+ BOOL bValueData;
+ String aContent;
+ if ( pCell )
+ {
+ switch ( pCell->GetCellType() )
+ {
+ case CELLTYPE_NOTE :
+ bValueData = FALSE;
+ break; // nix
+ case CELLTYPE_EDIT :
+ {
+ bValueData = FALSE;
+ EditEngine& rEngine = GetEditEngine();
+ const EditTextObject* pObj;
+ ((const ScEditCell*)pCell)->GetData( pObj );
+ if ( pObj )
+ {
+ rEngine.SetText( *pObj );
+ aContent = rEngine.GetText( LINEEND_LF ); // LineFeed zwischen Absaetzen!
+ }
+ }
+ break;
+ default:
+ {
+ bValueData = pCell->HasValueData();
+ ULONG nFormat = pAttr->GetNumberFormat( pFormatter );
+ Color* pColor;
+ ScCellFormat::GetString( pCell, nFormat, aContent, &pColor, *pFormatter );
+ }
+ }
+ }
+ else
+ bValueData = FALSE;
+
+ BOOL bResetPar, bResetAttr;
+ bResetPar = bResetAttr = FALSE;
+
+ const SvxHorJustifyItem& rHorJustifyItem = (const SvxHorJustifyItem&)pAttr->GetItem( ATTR_HOR_JUSTIFY );
+ const SvxWeightItem& rWeightItem = (const SvxWeightItem&) pAttr->GetItem( ATTR_FONT_WEIGHT );
+ const SvxPostureItem& rPostureItem = (const SvxPostureItem&) pAttr->GetItem( ATTR_FONT_POSTURE );
+ const SvxUnderlineItem& rUnderlineItem = (const SvxUnderlineItem&) pAttr->GetItem( ATTR_FONT_UNDERLINE );
+
+ const sal_Char* pChar;
+
+ switch( rHorJustifyItem.GetValue() )
+ {
+ case SVX_HOR_JUSTIFY_STANDARD:
+ pChar = (bValueData ? OOO_STRING_SVTOOLS_RTF_QR : OOO_STRING_SVTOOLS_RTF_QL);
+ break;
+ case SVX_HOR_JUSTIFY_CENTER: pChar = OOO_STRING_SVTOOLS_RTF_QC; break;
+ case SVX_HOR_JUSTIFY_BLOCK: pChar = OOO_STRING_SVTOOLS_RTF_QJ; break;
+ case SVX_HOR_JUSTIFY_RIGHT: pChar = OOO_STRING_SVTOOLS_RTF_QR; break;
+ case SVX_HOR_JUSTIFY_LEFT:
+ case SVX_HOR_JUSTIFY_REPEAT:
+ default: pChar = OOO_STRING_SVTOOLS_RTF_QL; break;
+ }
+ rStrm << pChar;
+
+ if ( rWeightItem.GetWeight() >= WEIGHT_BOLD )
+ { // bold
+ bResetAttr = TRUE;
+ rStrm << OOO_STRING_SVTOOLS_RTF_B;
+ }
+ if ( rPostureItem.GetPosture() != ITALIC_NONE )
+ { // italic
+ bResetAttr = TRUE;
+ rStrm << OOO_STRING_SVTOOLS_RTF_I;
+ }
+ if ( rUnderlineItem.GetLineStyle() != UNDERLINE_NONE )
+ { // underline
+ bResetAttr = TRUE;
+ rStrm << OOO_STRING_SVTOOLS_RTF_UL;
+ }
+
+ rStrm << ' ';
+ RTFOutFuncs::Out_String( rStrm, aContent );
+ rStrm << OOO_STRING_SVTOOLS_RTF_CELL;
+
+ if ( bResetPar )
+ rStrm << OOO_STRING_SVTOOLS_RTF_PARD << OOO_STRING_SVTOOLS_RTF_INTBL;
+ if ( bResetAttr )
+ rStrm << OOO_STRING_SVTOOLS_RTF_PLAIN;
+}
+
+
diff --git a/sc/source/filter/rtf/rtfimp.cxx b/sc/source/filter/rtf/rtfimp.cxx
new file mode 100644
index 000000000000..83b48b1fa2b1
--- /dev/null
+++ b/sc/source/filter/rtf/rtfimp.cxx
@@ -0,0 +1,75 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+#ifndef PCH
+#include "global.hxx"
+#include "document.hxx"
+#include "filter.hxx"
+#endif
+#include "editutil.hxx"
+#include "rtfimp.hxx"
+#include "rtfparse.hxx"
+#include "ftools.hxx"
+
+
+FltError ScFormatFilterPluginImpl::ScImportRTF( SvStream &rStream, const String& rBaseURL, ScDocument *pDoc, ScRange& rRange )
+{
+ ScRTFImport aImp( pDoc, rRange );
+ FltError nErr = (FltError) aImp.Read( rStream, rBaseURL );
+ ScRange aR = aImp.GetRange();
+ rRange.aEnd = aR.aEnd;
+ aImp.WriteToDocument();
+ return nErr;
+}
+
+ScEEAbsImport *ScFormatFilterPluginImpl::CreateRTFImport( ScDocument* pDoc, const ScRange& rRange )
+{
+ return new ScRTFImport( pDoc, rRange );
+}
+
+
+ScRTFImport::ScRTFImport( ScDocument* pDocP, const ScRange& rRange ) :
+ ScEEImport( pDocP, rRange )
+{
+ mpParser = new ScRTFParser( mpEngine );
+}
+
+
+ScRTFImport::~ScRTFImport()
+{
+ // Reihenfolge wichtig, sonst knallt's irgendwann irgendwo in irgendeinem Dtor!
+ // Ist gewaehrleistet, da ScEEImport Basisklasse ist
+ delete (ScRTFParser*) mpParser; // vor EditEngine!
+}
+
+
+
diff --git a/sc/source/filter/rtf/rtfparse.cxx b/sc/source/filter/rtf/rtfparse.cxx
new file mode 100644
index 000000000000..b3373bbf4596
--- /dev/null
+++ b/sc/source/filter/rtf/rtfparse.cxx
@@ -0,0 +1,420 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+
+//------------------------------------------------------------------------
+
+#include "scitems.hxx"
+#include <editeng/eeitem.hxx>
+
+
+#include <editeng/editeng.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/svxrtf.hxx>
+#include <vcl/outdev.hxx>
+#include <svtools/rtftoken.h>
+
+#define SC_RTFPARSE_CXX
+#include "rtfparse.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "docpool.hxx"
+
+#define SC_RTFTWIPTOL 10 // 10 Twips Toleranz bei Spaltenbestimmung
+
+
+
+SV_IMPL_VARARR_SORT( ScRTFColTwips, ULONG );
+
+
+
+ScRTFParser::ScRTFParser( EditEngine* pEditP ) :
+ ScEEParser( pEditP ),
+ pDefaultList( new ScRTFDefaultList ),
+ pColTwips( new ScRTFColTwips ),
+ pActDefault( NULL ),
+ pDefMerge( NULL ),
+ nStartAdjust( (ULONG)~0 ),
+ nLastWidth(0),
+ bNewDef( FALSE )
+{
+ // RTF default FontSize 12Pt
+ long nMM = OutputDevice::LogicToLogic( 12, MAP_POINT, MAP_100TH_MM );
+ pPool->SetPoolDefaultItem( SvxFontHeightItem( nMM, 100, EE_CHAR_FONTHEIGHT ) );
+ // freifliegender pInsDefault
+ pInsDefault = new ScRTFCellDefault( pPool );
+}
+
+
+ScRTFParser::~ScRTFParser()
+{
+ delete pInsDefault;
+ delete pColTwips;
+ for ( ScRTFCellDefault* pD = pDefaultList->First(); pD; pD = pDefaultList->Next() )
+ delete pD;
+ delete pDefaultList;
+}
+
+
+ULONG ScRTFParser::Read( SvStream& rStream, const String& rBaseURL )
+{
+ Link aOldLink = pEdit->GetImportHdl();
+ pEdit->SetImportHdl( LINK( this, ScRTFParser, RTFImportHdl ) );
+ ULONG nErr = pEdit->Read( rStream, rBaseURL, EE_FORMAT_RTF );
+ if ( nLastToken == RTF_PAR )
+ {
+ ScEEParseEntry* pE = pList->Last();
+ if ( pE
+ // komplett leer
+ && (( pE->aSel.nStartPara == pE->aSel.nEndPara
+ && pE->aSel.nStartPos == pE->aSel.nEndPos)
+ // leerer Paragraph
+ || ( pE->aSel.nStartPara + 1 == pE->aSel.nEndPara
+ && pE->aSel.nStartPos == pEdit->GetTextLen( pE->aSel.nStartPara )
+ && pE->aSel.nEndPos == 0 )) )
+ { // den letzten leeren Absatz nicht uebernehmen
+ pList->Remove();
+ delete pE;
+ }
+ }
+ ColAdjust();
+ pEdit->SetImportHdl( aOldLink );
+ return nErr;
+}
+
+
+void ScRTFParser::EntryEnd( ScEEParseEntry* pE, const ESelection& aSel )
+{
+ // Paragraph -2 stript den angehaengten leeren Paragraph
+ pE->aSel.nEndPara = aSel.nEndPara - 2;
+ // obwohl das nEndPos heisst, ist das letzte Position + 1
+ pE->aSel.nEndPos = pEdit->GetTextLen( aSel.nEndPara - 1 );
+}
+
+
+inline void ScRTFParser::NextRow()
+{
+ if ( nRowMax < ++nRowCnt )
+ nRowMax = nRowCnt;
+}
+
+
+BOOL ScRTFParser::SeekTwips( USHORT nTwips, SCCOL* pCol )
+{
+ USHORT nPos;
+ BOOL bFound = pColTwips->Seek_Entry( nTwips, &nPos );
+ *pCol = static_cast<SCCOL>(nPos);
+ if ( bFound )
+ return TRUE;
+ USHORT nCount = pColTwips->Count();
+ if ( !nCount )
+ return FALSE;
+ SCCOL nCol = *pCol;
+ // nCol ist Einfuegeposition, da liegt der Naechsthoehere (oder auch nicht)
+ if ( nCol < static_cast<SCCOL>(nCount) && (((*pColTwips)[nCol] - SC_RTFTWIPTOL) <= nTwips) )
+ return TRUE;
+ // nicht kleiner als alles andere? dann mit Naechstniedrigerem vergleichen
+ else if ( nCol != 0 && (((*pColTwips)[nCol-1] + SC_RTFTWIPTOL) >= nTwips) )
+ {
+ (*pCol)--;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+void ScRTFParser::ColAdjust()
+{
+ if ( nStartAdjust != (ULONG)~0 )
+ {
+ SCCOL nCol = 0;
+ ScEEParseEntry* pE;
+ pE = pList->Seek( nStartAdjust );
+ while ( pE )
+ {
+ if ( pE->nCol == 0 )
+ nCol = 0;
+ pE->nCol = nCol;
+ if ( pE->nColOverlap > 1 )
+ nCol = nCol + pE->nColOverlap; // merged cells mit \clmrg
+ else
+ {
+ SeekTwips( pE->nTwips, &nCol );
+ if ( ++nCol <= pE->nCol )
+ nCol = pE->nCol + 1; // verschobene Zell-X
+ pE->nColOverlap = nCol - pE->nCol; // merged cells ohne \clmrg
+ }
+ if ( nCol > nColMax )
+ nColMax = nCol;
+ pE = pList->Next();
+ }
+ nStartAdjust = (ULONG)~0;
+ pColTwips->Remove( (USHORT)0, pColTwips->Count() );
+ }
+}
+
+
+IMPL_LINK( ScRTFParser, RTFImportHdl, ImportInfo*, pInfo )
+{
+ switch ( pInfo->eState )
+ {
+ case RTFIMP_NEXTTOKEN:
+ ProcToken( pInfo );
+ break;
+ case RTFIMP_UNKNOWNATTR:
+ ProcToken( pInfo );
+ break;
+ case RTFIMP_START:
+ {
+ SvxRTFParser* pParser = (SvxRTFParser*) pInfo->pParser;
+ pParser->SetAttrPool( pPool );
+ RTFPardAttrMapIds& rMap = pParser->GetPardMap();
+ rMap.nBrush = ATTR_BACKGROUND;
+ rMap.nBox = ATTR_BORDER;
+ rMap.nShadow = ATTR_SHADOW;
+ }
+ break;
+ case RTFIMP_END:
+ if ( pInfo->aSelection.nEndPos )
+ { // falls noch Text: letzten Absatz erzeugen
+ pActDefault = NULL;
+ pInfo->nToken = RTF_PAR;
+ // EditEngine hat keinen leeren Paragraph mehr angehaengt
+ // den EntryEnd strippen koennte
+ pInfo->aSelection.nEndPara++;
+ ProcToken( pInfo );
+ }
+ break;
+ case RTFIMP_SETATTR:
+ break;
+ case RTFIMP_INSERTTEXT:
+ break;
+ case RTFIMP_INSERTPARA:
+ break;
+ default:
+ DBG_ERRORFILE("unknown ImportInfo.eState");
+ }
+ return 0;
+}
+
+
+// bei RTF_INTBL bzw. am Anfang von erstem RTF_CELL nach RTF_CELLX wenn es
+// kein RTF_INTBL gab, bad behavior
+void ScRTFParser::NewCellRow( ImportInfo* /*pInfo*/ )
+{
+ if ( bNewDef )
+ {
+ ScRTFCellDefault* pD;
+ bNewDef = FALSE;
+ // rechts nicht buendig? => neue Tabelle
+ if ( nLastWidth
+ && ((pD = pDefaultList->Last()) != 0) && pD->nTwips != nLastWidth )
+ {
+ SCCOL n1, n2;
+ if ( !( SeekTwips( nLastWidth, &n1 )
+ && SeekTwips( pD->nTwips, &n2 ) && n1 == n2) )
+ ColAdjust();
+ }
+ // TwipCols aufbauen, erst nach nLastWidth Vergleich!
+ for ( pD = pDefaultList->First(); pD; pD = pDefaultList->Next() )
+ {
+ SCCOL n;
+ if ( !SeekTwips( pD->nTwips, &n ) )
+ pColTwips->Insert( pD->nTwips );
+ }
+ }
+ pDefMerge = NULL;
+ pActDefault = pDefaultList->First();
+ DBG_ASSERT( pActDefault, "NewCellRow: pActDefault==0" );
+}
+
+
+/*
+ SW:
+ ~~~
+ [\par]
+ \trowd \cellx \cellx ...
+ \intbl \cell \cell ...
+ \row
+ [\par]
+ [\trowd \cellx \cellx ...]
+ \intbl \cell \cell ...
+ \row
+ [\par]
+
+ M$-Word:
+ ~~~~~~~~
+ [\par]
+ \trowd \cellx \cellx ...
+ \intbl \cell \cell ...
+ \intbl \row
+ [\par]
+ [\trowd \cellx \cellx ...]
+ \intbl \cell \cell ...
+ \intbl \row
+ [\par]
+
+ */
+
+void ScRTFParser::ProcToken( ImportInfo* pInfo )
+{
+ ScRTFCellDefault* pD;
+ ScEEParseEntry* pE;
+ switch ( pInfo->nToken )
+ {
+ case RTF_TROWD: // denotes table row defauls, before RTF_CELLX
+ {
+ if ( (pD = pDefaultList->Last()) != 0 )
+ nLastWidth = pD->nTwips;
+ nColCnt = 0;
+ for ( pD = pDefaultList->First(); pD; pD = pDefaultList->Next() )
+ delete pD;
+ pDefaultList->Clear();
+ pDefMerge = NULL;
+ nLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_CLMGF: // The first cell of cells to be merged
+ {
+ pDefMerge = pInsDefault;
+ nLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_CLMRG: // A cell to be merged with the preceding cell
+ {
+ if ( !pDefMerge )
+ pDefMerge = pDefaultList->Last();
+ DBG_ASSERT( pDefMerge, "RTF_CLMRG: pDefMerge==0" );
+ if ( pDefMerge ) // sonst rottes RTF
+ pDefMerge->nColOverlap++; // mehrere nacheinander moeglich
+ pInsDefault->nColOverlap = 0; // Flag: ignoriere diese
+ nLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_CELLX: // closes cell default
+ {
+ bNewDef = TRUE;
+ pInsDefault->nCol = nColCnt;
+ pInsDefault->nTwips = pInfo->nTokenValue; // rechter Zellenrand
+ pDefaultList->Insert( pInsDefault, LIST_APPEND );
+ // neuer freifliegender pInsDefault
+ pInsDefault = new ScRTFCellDefault( pPool );
+ if ( ++nColCnt > nColMax )
+ nColMax = nColCnt;
+ nLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_INTBL: // before the first RTF_CELL
+ {
+ // einmal ueber NextToken und einmal ueber UnknownAttrToken
+ // oder z.B. \intbl ... \cell \pard \intbl ... \cell
+ if ( nLastToken != RTF_INTBL && nLastToken != RTF_CELL && nLastToken != RTF_PAR )
+ {
+ NewCellRow( pInfo );
+ nLastToken = pInfo->nToken;
+ }
+ }
+ break;
+ case RTF_CELL: // denotes the end of a cell.
+ {
+ DBG_ASSERT( pActDefault, "RTF_CELL: pActDefault==0" );
+ if ( bNewDef || !pActDefault )
+ NewCellRow( pInfo ); // davor war kein \intbl, bad behavior
+ // rottes RTF? retten was zu retten ist
+ if ( !pActDefault )
+ pActDefault = pInsDefault;
+ if ( pActDefault->nColOverlap > 0 )
+ { // nicht merged mit vorheriger
+ pActEntry->nCol = pActDefault->nCol;
+ pActEntry->nColOverlap = pActDefault->nColOverlap;
+ pActEntry->nTwips = pActDefault->nTwips;
+ pActEntry->nRow = nRowCnt;
+ pActEntry->aItemSet.Set( pActDefault->aItemSet );
+ EntryEnd( pActEntry, pInfo->aSelection );
+
+ if ( nStartAdjust == (ULONG)~0 )
+ nStartAdjust = pList->Count();
+ pList->Insert( pActEntry, LIST_APPEND );
+ NewActEntry( pActEntry ); // neuer freifliegender pActEntry
+ }
+ else
+ { // aktuelle Twips der MergeCell zuweisen
+ if ( (pE = pList->Last()) != 0 )
+ pE->nTwips = pActDefault->nTwips;
+ // Selection des freifliegenden pActEntry anpassen
+ // Paragraph -1 wg. Textaufbruch in EditEngine waehrend Parse
+ pActEntry->aSel.nStartPara = pInfo->aSelection.nEndPara - 1;
+ }
+ pActDefault = pDefaultList->Next();
+ nLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_ROW: // means the end of a row
+ {
+ NextRow();
+ nLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_PAR: // Paragraph
+ {
+ if ( !pActDefault )
+ { // text not in table
+ ColAdjust(); // close the processing table
+ pActEntry->nCol = 0;
+ pActEntry->nRow = nRowCnt;
+ EntryEnd( pActEntry, pInfo->aSelection );
+ pList->Insert( pActEntry, LIST_APPEND );
+ NewActEntry( pActEntry ); // new pActEntry
+ NextRow();
+ }
+ nLastToken = pInfo->nToken;
+ }
+ break;
+ default:
+ { // do not set nLastToken
+ switch ( pInfo->nToken & ~(0xff | RTF_TABLEDEF) )
+ {
+ case RTF_SHADINGDEF:
+ ((SvxRTFParser*)pInfo->pParser)->ReadBackgroundAttr(
+ pInfo->nToken, pInsDefault->aItemSet, TRUE );
+ break;
+ case RTF_BRDRDEF:
+ ((SvxRTFParser*)pInfo->pParser)->ReadBorderAttr(
+ pInfo->nToken, pInsDefault->aItemSet, TRUE );
+ break;
+ }
+ }
+ }
+}
+
+
+
+