1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <vector>
22 
23 #include <com/sun/star/table/XTable.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 
26 #include <tools/diagnose_ex.h>
27 #include <tools/stream.hxx>
28 #include <tools/UnitConversion.hxx>
29 #include <svtools/rtfkeywd.hxx>
30 #include <svtools/rtfout.hxx>
31 
32 #include <editeng/eeitem.hxx>
33 #include <svx/sdtaitm.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <editeng/postitem.hxx>
36 #include <editeng/udlnitem.hxx>
37 
38 #include <cell.hxx>
39 #include <svx/svdotable.hxx>
40 #include <svx/svdoutl.hxx>
41 #include <editeng/editeng.hxx>
42 #include <editeng/outlobj.hxx>
43 
44 
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::table;
47 using namespace ::com::sun::star::container;
48 using namespace ::com::sun::star::beans;
49 
50 namespace sdr::table {
51 
52 class SdrTableRtfExporter
53 {
54 public:
55     SdrTableRtfExporter( SvStream& rStrmP, SdrTableObj& rObj );
56     void Write();
57     void WriteRow( const Reference< XPropertySet >& xRowSet, sal_Int32 nRow, const std::vector< sal_Int32 >& aColumnStart );
58     void WriteCell( sal_Int32 nCol, sal_Int32 nRow );
59 
60 private:
61     SvStream& mrStrm;
62     SdrTableObj& mrObj;
63     Reference< XTable > mxTable;
64 };
65 
ExportAsRTF(SvStream & rStrm,SdrTableObj & rObj)66 void ExportAsRTF( SvStream& rStrm, SdrTableObj& rObj )
67 {
68     SdrTableRtfExporter aEx( rStrm, rObj );
69     aEx.Write();
70 }
71 
72 constexpr OUStringLiteral gsSize( u"Size" );
73 
SdrTableRtfExporter(SvStream & rStrm,SdrTableObj & rObj)74 SdrTableRtfExporter::SdrTableRtfExporter( SvStream& rStrm, SdrTableObj& rObj )
75 : mrStrm( rStrm )
76 , mrObj( rObj )
77 , mxTable( rObj.getTable() )
78 {
79 }
80 
Write()81 void SdrTableRtfExporter::Write()
82 {
83     mrStrm.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RTF );
84     mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ANSI ).WriteCharPtr( SAL_NEWLINE_STRING );
85 
86     Reference< XTableColumns > xColumns( mxTable->getColumns() );
87     const sal_Int32 nColCount = xColumns->getCount();
88 
89     std::vector< sal_Int32 > aColumnStart;
90     aColumnStart.reserve( nColCount );
91 
92     // determine right offset of cells
93     sal_Int32 nPos = 0;
94     for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ ) try
95     {
96         Reference< XPropertySet > xSet( xColumns->getByIndex(nCol), UNO_QUERY_THROW );
97         sal_Int32 nWidth = 0;
98         xSet->getPropertyValue( gsSize ) >>= nWidth;
99         nPos += convertMm100ToTwip(nWidth);
100         aColumnStart.push_back( nPos );
101     }
102     catch( Exception& )
103     {
104         TOOLS_WARN_EXCEPTION("svx", "");
105     }
106 
107     // export rows
108     Reference< XTableRows > xRows( mxTable->getRows() );
109     const sal_Int32 nRowCount = xRows->getCount();
110 
111     for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ ) try
112     {
113         Reference< XPropertySet > xRowSet( xRows->getByIndex(nRow), UNO_QUERY_THROW );
114         WriteRow( xRowSet, nRow, aColumnStart );
115     }
116     catch( Exception& )
117     {
118         TOOLS_WARN_EXCEPTION("svx", "");
119     }
120 
121     mrStrm.WriteChar( '}' ).WriteCharPtr( SAL_NEWLINE_STRING );
122 }
123 
WriteRow(const Reference<XPropertySet> & xRowSet,sal_Int32 nRow,const std::vector<sal_Int32> & aColumnStart)124 void SdrTableRtfExporter::WriteRow( const Reference< XPropertySet >& xRowSet, sal_Int32 nRow, const std::vector< sal_Int32 >& aColumnStart )
125 {
126     sal_Int32 nRowHeight = 0;
127     xRowSet->getPropertyValue( gsSize ) >>= nRowHeight;
128 
129     mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TROWD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRGAPH ).WriteCharPtr( "30" ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRLEFT ).WriteCharPtr( "-30" );
130     mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRRH ).WriteOString( OString::number(nRowHeight) );
131 
132     const sal_Int32 nColCount = mxTable->getColumnCount();
133     for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ )
134     {
135         CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
136 
137         if( !xCell.is() )
138             continue;
139 
140         mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELLX ).WriteOString( OString::number(aColumnStart[nCol]) );
141         if ( (nCol & 0x0F) == 0x0F )
142             mrStrm.WriteCharPtr( SAL_NEWLINE_STRING );        // prevent long lines
143     }
144     mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PARD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PLAIN ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_INTBL ).WriteCharPtr( SAL_NEWLINE_STRING );
145 
146     sal_uLong nStrmPos = mrStrm.Tell();
147     for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ )
148     {
149         WriteCell( nCol, nRow );
150         if ( mrStrm.Tell() - nStrmPos > 255 )
151         {
152             mrStrm.WriteCharPtr( SAL_NEWLINE_STRING );
153             nStrmPos = mrStrm.Tell();
154         }
155     }
156     mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ROW ).WriteCharPtr( SAL_NEWLINE_STRING );
157 }
158 
159 
WriteCell(sal_Int32 nCol,sal_Int32 nRow)160 void SdrTableRtfExporter::WriteCell( sal_Int32 nCol, sal_Int32 nRow )
161 {
162     CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
163 
164     if( !xCell.is() || xCell->isMerged() )
165     {
166         mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELL );
167         return ;
168     }
169 
170     OUString aContent;
171 
172     OutlinerParaObject* pParaObj = xCell->CreateEditOutlinerParaObject().release();
173     bool bOwnParaObj = pParaObj != nullptr;
174 
175     if( pParaObj == nullptr )
176         pParaObj = xCell->GetOutlinerParaObject();
177 
178     if(pParaObj)
179     {
180         // handle outliner attributes
181         SdrOutliner& rOutliner = mrObj.ImpGetDrawOutliner();
182         rOutliner.SetText(*pParaObj);
183 
184         aContent = rOutliner.GetEditEngine().GetText();
185 
186         rOutliner.Clear();
187 
188         if( bOwnParaObj )
189             delete pParaObj;
190     }
191 
192     bool bResetAttr = false;
193 
194     SdrTextHorzAdjust eHAdj = xCell->GetTextHorizontalAdjust();
195 
196     const SfxItemSet& rCellSet = xCell->GetItemSet();
197 
198     const SvxWeightItem&        rWeightItem     = rCellSet.Get( EE_CHAR_WEIGHT );
199     const SvxPostureItem&       rPostureItem    = rCellSet.Get( EE_CHAR_ITALIC );
200     const SvxUnderlineItem&     rUnderlineItem  = rCellSet.Get( EE_CHAR_UNDERLINE );
201 
202     const char* pChar;
203 
204     switch( eHAdj )
205     {
206         case SDRTEXTHORZADJUST_CENTER:  pChar = OOO_STRING_SVTOOLS_RTF_QC;  break;
207         case SDRTEXTHORZADJUST_BLOCK:   pChar = OOO_STRING_SVTOOLS_RTF_QJ;  break;
208         case SDRTEXTHORZADJUST_RIGHT:   pChar = OOO_STRING_SVTOOLS_RTF_QR;  break;
209         case SDRTEXTHORZADJUST_LEFT:
210         default:                        pChar = OOO_STRING_SVTOOLS_RTF_QL;  break;
211     }
212     mrStrm.WriteCharPtr( pChar );
213 
214     if ( rWeightItem.GetWeight() >= WEIGHT_BOLD )
215     {   // bold
216         bResetAttr = true;
217         mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B );
218     }
219     if ( rPostureItem.GetPosture() != ITALIC_NONE )
220     {   // italic
221         bResetAttr = true;
222         mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I );
223     }
224     if ( rUnderlineItem.GetLineStyle() != LINESTYLE_NONE )
225     {   // underline
226         bResetAttr = true;
227         mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UL );
228     }
229 
230     mrStrm.WriteChar( ' ' );
231     RTFOutFuncs::Out_String( mrStrm, aContent );
232     mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELL );
233 
234     if ( bResetAttr )
235         mrStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PLAIN );
236 }
237 
238 }
239 
240 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
241