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 #include <scitems.hxx>
21 
22 #include <editeng/wghtitem.hxx>
23 #include <editeng/postitem.hxx>
24 #include <editeng/udlnitem.hxx>
25 #include <editeng/justifyitem.hxx>
26 #include <svtools/rtfout.hxx>
27 #include <svtools/rtfkeywd.hxx>
28 #include <tools/stream.hxx>
29 
30 #include <rtfexp.hxx>
31 #include <cellvalue.hxx>
32 #include <document.hxx>
33 #include <patattr.hxx>
34 #include <attrib.hxx>
35 #include <cellform.hxx>
36 #include <editutil.hxx>
37 #include <ftools.hxx>
38 
ScExportRTF(SvStream & rStrm,ScDocument * pDoc,const ScRange & rRange,const rtl_TextEncoding)39 void ScFormatFilterPluginImpl::ScExportRTF( SvStream& rStrm, ScDocument* pDoc,
40         const ScRange& rRange, const rtl_TextEncoding /*eNach*/ )
41 {
42     ScRTFExport aEx( rStrm, pDoc, rRange );
43     aEx.Write();
44 }
45 
ScRTFExport(SvStream & rStrmP,ScDocument * pDocP,const ScRange & rRangeP)46 ScRTFExport::ScRTFExport( SvStream& rStrmP, ScDocument* pDocP, const ScRange& rRangeP )
47             :
48             ScExportBase( rStrmP, pDocP, rRangeP ),
49             pCellX( new sal_uLong[ pDoc->MaxCol()+2 ] )
50 {
51 }
52 
~ScRTFExport()53 ScRTFExport::~ScRTFExport()
54 {
55 }
56 
Write()57 void ScRTFExport::Write()
58 {
59     rStrm.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RTF );
60     rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ANSI ).WriteCharPtr( SAL_NEWLINE_STRING );
61 
62     // Data
63     for ( SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); nTab++ )
64     {
65         if ( nTab > aRange.aStart.Tab() )
66             rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PAR );
67         WriteTab( nTab );
68     }
69 
70     rStrm.WriteChar( '}' ).WriteCharPtr( SAL_NEWLINE_STRING );
71 }
72 
WriteTab(SCTAB nTab)73 void ScRTFExport::WriteTab( SCTAB nTab )
74 {
75     rStrm.WriteChar( '{' ).WriteCharPtr( SAL_NEWLINE_STRING );
76     if ( pDoc->HasTable( nTab ) )
77     {
78         memset( &pCellX[0], 0, (pDoc->MaxCol()+2) * sizeof(sal_uLong) );
79         SCCOL nCol;
80         SCCOL nEndCol = aRange.aEnd.Col();
81         for ( nCol = aRange.aStart.Col(); nCol <= nEndCol; nCol++ )
82         {
83             pCellX[nCol+1] = pCellX[nCol] + pDoc->GetColWidth( nCol, nTab );
84         }
85 
86         SCROW nEndRow = aRange.aEnd.Row();
87         for ( SCROW nRow = aRange.aStart.Row(); nRow <= nEndRow; nRow++ )
88         {
89             WriteRow( nTab, nRow );
90         }
91     }
92     rStrm.WriteChar( '}' ).WriteCharPtr( SAL_NEWLINE_STRING );
93 }
94 
WriteRow(SCTAB nTab,SCROW nRow)95 void ScRTFExport::WriteRow( SCTAB nTab, SCROW nRow )
96 {
97     rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TROWD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRGAPH ).WriteCharPtr( "30" ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRLEFT ).WriteCharPtr( "-30" );
98     rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRRH ).WriteOString( OString::number(pDoc->GetRowHeight(nRow, nTab)) );
99     SCCOL nCol;
100     SCCOL nEndCol = aRange.aEnd.Col();
101     for ( nCol = aRange.aStart.Col(); nCol <= nEndCol; nCol++ )
102     {
103         const ScPatternAttr* pAttr = pDoc->GetPattern( nCol, nRow, nTab );
104         const ScMergeAttr&      rMergeAttr      = pAttr->GetItem( ATTR_MERGE );
105         const SvxVerJustifyItem& rVerJustifyItem= pAttr->GetItem( ATTR_VER_JUSTIFY );
106 
107         const char* pChar;
108 
109         if ( rMergeAttr.GetColMerge() != 0 )
110             rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CLMGF );
111         else
112         {
113             const ScMergeFlagAttr& rMergeFlagAttr = pAttr->GetItem( ATTR_MERGE_FLAG );
114             if ( rMergeFlagAttr.IsHorOverlapped() )
115                 rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CLMRG );
116         }
117 
118         switch( rVerJustifyItem.GetValue() )
119         {
120             case SvxCellVerJustify::Top:       pChar = OOO_STRING_SVTOOLS_RTF_CLVERTALT;   break;
121             case SvxCellVerJustify::Center:    pChar = OOO_STRING_SVTOOLS_RTF_CLVERTALC;   break;
122             case SvxCellVerJustify::Bottom:    pChar = OOO_STRING_SVTOOLS_RTF_CLVERTALB;   break;
123             case SvxCellVerJustify::Standard:  pChar = OOO_STRING_SVTOOLS_RTF_CLVERTALB;   break;  //! Bottom
124             default:                           pChar = nullptr;           break;
125         }
126         if ( pChar )
127             rStrm.WriteCharPtr( pChar );
128 
129         rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELLX ).WriteOString( OString::number(pCellX[nCol+1]) );
130         if ( (nCol & 0x0F) == 0x0F )
131             rStrm.WriteCharPtr( SAL_NEWLINE_STRING ); // Do not let lines get too long
132     }
133     rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PARD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PLAIN ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_INTBL ).WriteCharPtr( SAL_NEWLINE_STRING );
134 
135     sal_uLong nStrmPos = rStrm.Tell();
136     for ( nCol = aRange.aStart.Col(); nCol <= nEndCol; nCol++ )
137     {
138         WriteCell( nTab, nRow, nCol );
139         if ( rStrm.Tell() - nStrmPos > 255 )
140         {   // Do not let lines get too long
141             rStrm.WriteCharPtr( SAL_NEWLINE_STRING );
142             nStrmPos = rStrm.Tell();
143         }
144     }
145     rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ROW ).WriteCharPtr( SAL_NEWLINE_STRING );
146 }
147 
WriteCell(SCTAB nTab,SCROW nRow,SCCOL nCol)148 void ScRTFExport::WriteCell( SCTAB nTab, SCROW nRow, SCCOL nCol )
149 {
150     const ScPatternAttr* pAttr = pDoc->GetPattern( nCol, nRow, nTab );
151 
152     const ScMergeFlagAttr& rMergeFlagAttr = pAttr->GetItem( ATTR_MERGE_FLAG );
153     if ( rMergeFlagAttr.IsHorOverlapped() )
154     {
155         rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELL );
156         return ;
157     }
158 
159     bool bValueData = false;
160     OUString aContent;
161     ScAddress aPos(nCol, nRow, nTab);
162     ScRefCellValue aCell(*pDoc, aPos);
163     switch (aCell.meType)
164     {
165         case CELLTYPE_NONE:
166             bValueData = false;
167         break;
168         case CELLTYPE_EDIT:
169         {
170             bValueData = false;
171             const EditTextObject* pObj = aCell.mpEditText;
172             EditEngine& rEngine = GetEditEngine();
173             rEngine.SetText(*pObj);
174             aContent = rEngine.GetText(); // LineFeed in between paragraphs!
175         }
176         break;
177         default:
178         {
179             bValueData = pDoc->HasValueData(aPos);
180             sal_uInt32 nFormat = pAttr->GetNumberFormat(pFormatter);
181             const Color* pColor;
182             aContent = ScCellFormat::GetString(*pDoc, aPos, nFormat, &pColor, *pFormatter);
183         }
184     }
185 
186     bool bResetAttr(false);
187 
188     const SvxHorJustifyItem&    rHorJustifyItem = pAttr->GetItem( ATTR_HOR_JUSTIFY );
189     const SvxWeightItem&        rWeightItem     = pAttr->GetItem( ATTR_FONT_WEIGHT );
190     const SvxPostureItem&       rPostureItem    = pAttr->GetItem( ATTR_FONT_POSTURE );
191     const SvxUnderlineItem&     rUnderlineItem  = pAttr->GetItem( ATTR_FONT_UNDERLINE );
192 
193     const char* pChar;
194 
195     switch( rHorJustifyItem.GetValue() )
196     {
197         case SvxCellHorJustify::Standard:
198             pChar = (bValueData ? OOO_STRING_SVTOOLS_RTF_QR : OOO_STRING_SVTOOLS_RTF_QL);
199             break;
200         case SvxCellHorJustify::Center:    pChar = OOO_STRING_SVTOOLS_RTF_QC;  break;
201         case SvxCellHorJustify::Block:     pChar = OOO_STRING_SVTOOLS_RTF_QJ;  break;
202         case SvxCellHorJustify::Right:     pChar = OOO_STRING_SVTOOLS_RTF_QR;  break;
203         case SvxCellHorJustify::Left:
204         case SvxCellHorJustify::Repeat:
205         default:                        pChar = OOO_STRING_SVTOOLS_RTF_QL;  break;
206     }
207     rStrm.WriteCharPtr( pChar );
208 
209     if ( rWeightItem.GetWeight() >= WEIGHT_BOLD )
210     {   // bold
211         bResetAttr = true;
212         rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B );
213     }
214     if ( rPostureItem.GetPosture() != ITALIC_NONE )
215     {   // italic
216         bResetAttr = true;
217         rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I );
218     }
219     if ( rUnderlineItem.GetLineStyle() != LINESTYLE_NONE )
220     {   // underline
221         bResetAttr = true;
222         rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UL );
223     }
224 
225     rStrm.WriteChar( ' ' );
226     RTFOutFuncs::Out_String( rStrm, aContent );
227     rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELL );
228 
229     if ( bResetAttr )
230         rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PLAIN );
231 }
232 
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
234