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