1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <osl/endian.h>
21 #include <tools/stream.hxx>
26 #include <fmtcntnt.hxx>
29 #include <frameformats.hxx>
30 #include <sfx2/docfile.hxx>
31 #include <sfx2/sfxsids.hrc>
32 #include <o3tl/string_view.hxx>
34 #include <strings.hrc>
36 SwASCWriter::SwASCWriter( std::u16string_view rFltNm
)
38 SwAsciiOptions aNewOpts
;
40 switch( 5 <= rFltNm
.size() ? rFltNm
[4] : 0 )
43 aNewOpts
.SetCharSet( RTL_TEXTENCODING_IBM_850
);
44 aNewOpts
.SetParaFlags( LINEEND_CRLF
);
45 if( 5 < rFltNm
.size() )
47 std::u16string_view aFilterNum
= rFltNm
.substr( 5 );
48 switch( o3tl::toInt32(aFilterNum
) )
50 case 437: aNewOpts
.SetCharSet( RTL_TEXTENCODING_IBM_437
); break;
51 case 850: aNewOpts
.SetCharSet( RTL_TEXTENCODING_IBM_850
); break;
52 case 860: aNewOpts
.SetCharSet( RTL_TEXTENCODING_IBM_860
); break;
53 case 861: aNewOpts
.SetCharSet( RTL_TEXTENCODING_IBM_861
); break;
54 case 863: aNewOpts
.SetCharSet( RTL_TEXTENCODING_IBM_863
); break;
55 case 865: aNewOpts
.SetCharSet( RTL_TEXTENCODING_IBM_865
); break;
62 aNewOpts
.SetCharSet( RTL_TEXTENCODING_MS_1252
);
63 aNewOpts
.SetParaFlags( LINEEND_CRLF
);
68 aNewOpts
.SetCharSet( RTL_TEXTENCODING_APPLE_ROMAN
);
69 aNewOpts
.SetParaFlags( LINEEND_CR
);
74 aNewOpts
.SetCharSet( RTL_TEXTENCODING_MS_1252
);
75 aNewOpts
.SetParaFlags( LINEEND_LF
);
80 if( rFltNm
.size() >= 4 && rFltNm
.substr( 4 )==u
"_DLG" )
83 aNewOpts
= GetAsciiOptions();
86 SetAsciiOptions( aNewOpts
);
89 SwASCWriter::~SwASCWriter() {}
91 ErrCode
SwASCWriter::WriteStream()
93 static constexpr OUString STR_CR
= u
"\015"_ustr
;
94 static constexpr OUStringLiteral STR_LF
= u
"\012";
95 static constexpr OUStringLiteral STR_CRLF
= u
"\015\012";
96 static constexpr OUStringLiteral STR_BLANK
= u
" ";
97 bool bIncludeBOM
= GetAsciiOptions().GetIncludeBOM();
98 bool bIncludeHidden
= GetAsciiOptions().GetIncludeHidden();
100 if( m_bASCII_ParaAsCR
) // If predefined
102 else if( m_bASCII_ParaAsBlank
)
103 m_sLineEnd
= STR_BLANK
;
105 switch( GetAsciiOptions().GetParaFlags() )
107 case LINEEND_CR
: m_sLineEnd
= STR_CR
; break;
108 case LINEEND_LF
: m_sLineEnd
= STR_LF
; break;
109 case LINEEND_CRLF
: m_sLineEnd
= STR_CRLF
; break;
112 SwNodeOffset nMaxNode
= m_pDoc
->GetNodes().Count();
114 if( m_bShowProgress
)
115 ::StartProgress( STR_STATSTR_W4WWRITE
, 0, sal_Int32(nMaxNode
), m_pDoc
->GetDocShell() );
117 SwPaM
* pPam
= m_pOrigPam
;
119 bool bWriteSttTag
= m_bUCS2_WithStartChar
&&
120 (RTL_TEXTENCODING_UCS2
== GetAsciiOptions().GetCharSet() ||
121 RTL_TEXTENCODING_UTF8
== GetAsciiOptions().GetCharSet());
123 rtl_TextEncoding eOld
= Strm().GetStreamCharSet();
124 Strm().SetStreamCharSet( GetAsciiOptions().GetCharSet() );
126 // Output all areas of the pam into the ASC file
129 while( m_pCurrentPam
->GetPoint()->GetNodeIndex() < m_pCurrentPam
->GetMark()->GetNodeIndex() ||
130 (m_pCurrentPam
->GetPoint()->GetNodeIndex() == m_pCurrentPam
->GetMark()->GetNodeIndex() &&
131 m_pCurrentPam
->GetPoint()->GetContentIndex() <= m_pCurrentPam
->GetMark()->GetContentIndex()) )
133 SwTextNode
* pNd
= m_pCurrentPam
->GetPoint()->GetNode().GetTextNode();
136 // Should we have frames only?
137 // That's possible, if we put a frame selection into the clipboard
138 if( bTstFly
&& m_bWriteAll
&&
139 pNd
->GetText().isEmpty() &&
141 !m_pDoc
->GetSpzFrameFormats()->empty() &&
142 // Only one node in the array
143 m_pDoc
->GetNodes().GetEndOfExtras().GetIndex() + 3 ==
144 m_pDoc
->GetNodes().GetEndOfContent().GetIndex() &&
145 // And exactly this one is selected
146 m_pDoc
->GetNodes().GetEndOfContent().GetIndex() - 1 ==
147 m_pCurrentPam
->GetPoint()->GetNodeIndex() )
149 // Print the frame's content.
150 // It is always at position 0!
151 const SwFrameFormat
* pFormat
= (*m_pDoc
->GetSpzFrameFormats())[ 0 ];
152 const SwNodeIndex
* pIdx
= pFormat
->GetContent().GetContentIdx();
155 m_pCurrentPam
= NewUnoCursor(*m_pDoc
, pIdx
->GetIndex(),
156 pIdx
->GetNode().EndOfSectionIndex() );
157 m_pCurrentPam
->Exchange();
158 continue; // reset while loop!
161 else if (!pNd
->IsHidden() || bIncludeHidden
)
165 switch(GetAsciiOptions().GetCharSet())
167 case RTL_TEXTENCODING_UTF8
:
170 Strm().WriteUChar( 0xEF ).WriteUChar( 0xBB ).WriteUChar( 0xBF );
174 case RTL_TEXTENCODING_UCS2
:
176 Strm().SetEndian(SvStreamEndian::LITTLE
);
178 Strm().SetEndian(SvStreamEndian::BIG
);
182 Strm().StartWritingUnicodeText();
187 bWriteSttTag
= false;
190 SwTableNode
* pTableNd
= pNd
->FindTableNode();
193 if (pTableNd
&& m_bWriteAll
)
194 WriteTable(pTableNd
, pNd
);
196 Out( aASCNodeFnTab
, *pNd
, *this );
198 bTstFly
= false; // Testing once is enough
201 if( !m_pCurrentPam
->Move( fnMoveForward
, GoInNode
) )
204 if( m_bShowProgress
)
205 ::SetProgressState( sal_Int32(m_pCurrentPam
->GetPoint()->GetNodeIndex()),
206 m_pDoc
->GetDocShell() ); // How far?
209 } while( CopyNextPam( &pPam
) ); // Until all pams are processed
211 Strm().SetStreamCharSet( eOld
);
213 if( m_bShowProgress
)
214 ::EndProgress( m_pDoc
->GetDocShell() );
219 void SwASCWriter::SetupFilterOptions(SfxMedium
& rMedium
)
221 if( const SfxStringItem
* pItem
= rMedium
.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS
) )
225 sItemOpt
= pItem
->GetValue();
226 aOpt
.ReadUserData(sItemOpt
);
227 SetAsciiOptions(aOpt
);
231 void SwASCWriter::WriteTable(SwTableNode
* pTableNd
, SwTextNode
* pNd
)
233 OUString sPreLineEnd
= this->m_sLineEnd
;
234 m_sLineEnd
= u
""_ustr
;
236 const SwTableLine
* pEndTabLine
= pTableNd
->GetTable().GetTabLines().back();
237 const SwTableBox
* pEndTabBox
= pEndTabLine
->GetTabBoxes().back();
239 for( const SwTableLine
* pLine
: pTableNd
->GetTable().GetTabLines() )
241 for( const SwTableBox
* pBox
: pLine
->GetTabBoxes() )
243 Out( aASCNodeFnTab
, *pNd
, *this );
246 const SwTableBox
* pTableBox
= pNd
->GetTableBox();
248 aPrevBoxPoint
= pTableBox
->GetCoordinates();
249 m_pCurrentPam
->Move(fnMoveForward
, GoInNode
);
250 pNd
= m_pCurrentPam
->GetPoint()->GetNode().GetTextNode();
251 pTableBox
= pNd
->GetTableBox();
253 // Line break in a box
254 // Each line is a new SwTextNode so we
255 // need to parse inside the current box
256 while (pTableBox
&& pTableBox
->GetCoordinates() == aPrevBoxPoint
)
258 Strm().WriteUnicodeOrByteText(sPreLineEnd
);
259 Out(aASCNodeFnTab
, *pNd
, *this);
261 m_pCurrentPam
->Move(fnMoveForward
, GoInNode
);
262 pNd
= m_pCurrentPam
->GetPoint()->GetNode().GetTextNode();
263 pTableBox
= pNd
->GetTableBox();
265 if (pBox
!= pLine
->GetTabBoxes().back())
266 Strm().WriteUChar( 0x9 );
268 if (pBox
== pEndTabBox
)
269 this->m_sLineEnd
= sPreLineEnd
;
273 if (pLine
== pEndTabLine
)
275 m_pCurrentPam
->Move(fnMoveBackward
, GoInNode
);
276 pNd
= m_pCurrentPam
->GetPoint()->GetNode().GetTextNode();
277 Strm().WriteUnicodeOrByteText( sPreLineEnd
);
279 if (pLine
!= pEndTabLine
)
280 Strm().WriteUnicodeOrByteText( sPreLineEnd
);
283 this->m_sLineEnd
= sPreLineEnd
;
287 std::u16string_view rFltNm
, [[maybe_unused
]] const OUString
& /*rBaseURL*/, WriterRef
& xRet
)
289 xRet
= new SwASCWriter( rFltNm
);
292 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */