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 <TokenWriter.hxx>
21 #include <tools/diagnose_ex.h>
22 #include <tools/stream.hxx>
23 #include <osl/diagnose.h>
24 #include <rtl/tencinfo.h>
25 #include <sal/log.hxx>
26 #include <i18nlangtag/languagetag.hxx>
27 #include <RtfReader.hxx>
28 #include <HtmlReader.hxx>
29 #include <strings.hxx>
30 #include <comphelper/types.hxx>
31 #include <connectivity/dbtools.hxx>
32 #include <com/sun/star/sdb/CommandType.hpp>
33 #include <com/sun/star/sdb/DatabaseContext.hpp>
34 #include <com/sun/star/sdbc/XConnection.hpp>
35 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
36 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
37 #include <com/sun/star/sdbc/XRowSet.hpp>
38 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
39 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
40 #include <com/sun/star/awt/FontWeight.hpp>
41 #include <com/sun/star/awt/FontStrikeout.hpp>
42 #include <com/sun/star/awt/FontSlant.hpp>
43 #include <com/sun/star/awt/FontUnderline.hpp>
44 #include <com/sun/star/document/DocumentProperties.hpp>
45 #include <svtools/htmlkywd.hxx>
46 #include <svtools/rtfkeywd.hxx>
47 #include <tools/color.hxx>
48 #include <svtools/htmlout.hxx>
49 #include <sfx2/frmhtmlw.hxx>
50 #include <svl/numuno.hxx>
51 #include <vcl/svapp.hxx>
52 #include <UITools.hxx>
53 #include <toolkit/helper/vclunohelper.hxx>
54 #include <vcl/outdev.hxx>
55 #include <vcl/settings.hxx>
56 #include <svtools/rtfout.hxx>
57 #include <svtools/htmlcfg.hxx>
58 #include <connectivity/formattedcolumnvalue.hxx>
59 #include <memory>
60
61 using namespace dbaui;
62 using namespace dbtools;
63 using namespace svx;
64 using namespace ::com::sun::star;
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::beans;
67 using namespace ::com::sun::star::container;
68 using namespace ::com::sun::star::sdbc;
69 using namespace ::com::sun::star::sdb;
70 using namespace ::com::sun::star::lang;
71 using namespace ::com::sun::star::sdbcx;
72 using namespace ::com::sun::star::awt;
73 using namespace ::com::sun::star::util;
74
75 #define CELL_X 1437
76
ODatabaseImportExport(const svx::ODataAccessDescriptor & _aDataDescriptor,const Reference<XComponentContext> & _rM,const Reference<css::util::XNumberFormatter> & _rxNumberF)77 ODatabaseImportExport::ODatabaseImportExport(const svx::ODataAccessDescriptor& _aDataDescriptor,
78 const Reference< XComponentContext >& _rM,
79 const Reference< css::util::XNumberFormatter >& _rxNumberF)
80 :m_bBookmarkSelection( false )
81 ,m_xFormatter(_rxNumberF)
82 ,m_xContext(_rM)
83 ,m_nCommandType(CommandType::TABLE)
84 ,m_bNeedToReInitialize(false)
85 ,m_bInInitialize(false)
86 ,m_bCheckOnly(false)
87 {
88 m_eDestEnc = osl_getThreadTextEncoding();
89
90 osl_atomic_increment( &m_refCount );
91 impl_initFromDescriptor( _aDataDescriptor, false );
92 osl_atomic_decrement( &m_refCount );
93 }
94
95 // import data
ODatabaseImportExport(const::dbtools::SharedConnection & _rxConnection,const Reference<XNumberFormatter> & _rxNumberF,const Reference<XComponentContext> & _rM)96 ODatabaseImportExport::ODatabaseImportExport( const ::dbtools::SharedConnection& _rxConnection,
97 const Reference< XNumberFormatter >& _rxNumberF, const Reference< XComponentContext >& _rM )
98 :m_bBookmarkSelection( false )
99 ,m_pStream(nullptr)
100 ,m_xConnection(_rxConnection)
101 ,m_xFormatter(_rxNumberF)
102 ,m_xContext(_rM)
103 ,m_nCommandType(css::sdb::CommandType::TABLE)
104 ,m_bNeedToReInitialize(false)
105 ,m_bInInitialize(false)
106 ,m_bCheckOnly(false)
107 {
108 m_eDestEnc = osl_getThreadTextEncoding();
109 }
110
~ODatabaseImportExport()111 ODatabaseImportExport::~ODatabaseImportExport()
112 {
113 acquire();
114 dispose();
115 }
116
dispose()117 void ODatabaseImportExport::dispose()
118 {
119 // remove me as listener
120 Reference< XComponent > xComponent(m_xConnection, UNO_QUERY);
121 if (xComponent.is())
122 {
123 Reference< XEventListener> xEvt(static_cast<cppu::OWeakObject*>(this),UNO_QUERY);
124 xComponent->removeEventListener(xEvt);
125 }
126 m_xConnection.clear();
127
128 ::comphelper::disposeComponent(m_xRow);
129
130 m_xObject.clear();
131 m_xResultSetMetaData.clear();
132 m_xResultSet.clear();
133 m_xRow.clear();
134 m_xRowLocate.clear();
135 m_xFormatter.clear();
136 }
137
disposing(const EventObject & Source)138 void SAL_CALL ODatabaseImportExport::disposing( const EventObject& Source )
139 {
140 Reference<XConnection> xCon(Source.Source,UNO_QUERY);
141 if(m_xConnection.is() && m_xConnection == xCon)
142 {
143 m_xConnection.clear();
144 dispose();
145 m_bNeedToReInitialize = true;
146 }
147 }
148
initialize(const ODataAccessDescriptor & _aDataDescriptor)149 void ODatabaseImportExport::initialize( const ODataAccessDescriptor& _aDataDescriptor )
150 {
151 impl_initFromDescriptor( _aDataDescriptor, true );
152 }
153
impl_initFromDescriptor(const ODataAccessDescriptor & _aDataDescriptor,bool _bPlusDefaultInit)154 void ODatabaseImportExport::impl_initFromDescriptor( const ODataAccessDescriptor& _aDataDescriptor, bool _bPlusDefaultInit)
155 {
156 if ( !_bPlusDefaultInit )
157 {
158 m_sDataSourceName = _aDataDescriptor.getDataSource();
159 _aDataDescriptor[DataAccessDescriptorProperty::CommandType] >>= m_nCommandType;
160 _aDataDescriptor[DataAccessDescriptorProperty::Command] >>= m_sName;
161 // some additional information
162 if(_aDataDescriptor.has(DataAccessDescriptorProperty::Connection))
163 {
164 Reference< XConnection > xPureConn( _aDataDescriptor[DataAccessDescriptorProperty::Connection], UNO_QUERY );
165 m_xConnection.reset( xPureConn, SharedConnection::NoTakeOwnership );
166 Reference< XEventListener> xEvt(static_cast<cppu::OWeakObject*>(this),UNO_QUERY);
167 Reference< XComponent > xComponent(m_xConnection, UNO_QUERY);
168 if (xComponent.is() && xEvt.is())
169 xComponent->addEventListener(xEvt);
170 }
171
172 if ( _aDataDescriptor.has( DataAccessDescriptorProperty::Selection ) )
173 _aDataDescriptor[ DataAccessDescriptorProperty::Selection ] >>= m_aSelection;
174
175 if ( _aDataDescriptor.has( DataAccessDescriptorProperty::BookmarkSelection ) )
176 _aDataDescriptor[ DataAccessDescriptorProperty::BookmarkSelection ] >>= m_bBookmarkSelection;
177
178 if ( _aDataDescriptor.has( DataAccessDescriptorProperty::Cursor ) )
179 {
180 _aDataDescriptor[ DataAccessDescriptorProperty::Cursor ] >>= m_xResultSet;
181 m_xRowLocate.set( m_xResultSet, UNO_QUERY );
182 }
183
184 if ( m_aSelection.hasElements() )
185 {
186 if ( !m_xResultSet.is() )
187 {
188 SAL_WARN("dbaccess.ui", "ODatabaseImportExport::impl_initFromDescriptor: selection without result set is nonsense!" );
189 m_aSelection.realloc( 0 );
190 }
191 }
192
193 if ( m_aSelection.hasElements() )
194 {
195 if ( m_bBookmarkSelection && !m_xRowLocate.is() )
196 {
197 SAL_WARN("dbaccess.ui", "ODatabaseImportExport::impl_initFromDescriptor: no XRowLocate -> no bookmarks!" );
198 m_aSelection.realloc( 0 );
199 }
200 }
201 }
202 else
203 initialize();
204 }
205
initialize()206 void ODatabaseImportExport::initialize()
207 {
208 m_bInInitialize = true;
209 m_bNeedToReInitialize = false;
210
211 if ( !m_xConnection.is() )
212 { // we need a connection
213 OSL_ENSURE(!m_sDataSourceName.isEmpty(),"There must be a datsource name!");
214 Reference<XNameAccess> xDatabaseContext( DatabaseContext::create(m_xContext), UNO_QUERY_THROW);
215 Reference< XEventListener> xEvt(static_cast<cppu::OWeakObject*>(this),UNO_QUERY);
216
217 Reference< XConnection > xConnection;
218 SQLExceptionInfo aInfo = ::dbaui::createConnection( m_sDataSourceName, xDatabaseContext, m_xContext, xEvt, xConnection );
219 m_xConnection.reset( xConnection );
220
221 if(aInfo.isValid() && aInfo.getType() == SQLExceptionInfo::TYPE::SQLException)
222 throw *static_cast<const SQLException*>(aInfo);
223 }
224
225 Reference<XNameAccess> xNameAccess;
226 switch(m_nCommandType)
227 {
228 case CommandType::TABLE:
229 {
230 // only for tables
231 Reference<XTablesSupplier> xSup(m_xConnection,UNO_QUERY);
232 if(xSup.is())
233 xNameAccess = xSup->getTables();
234 }
235 break;
236 case CommandType::QUERY:
237 {
238 Reference<XQueriesSupplier> xSup(m_xConnection,UNO_QUERY);
239 if(xSup.is())
240 xNameAccess = xSup->getQueries();
241 }
242 break;
243 }
244 if(xNameAccess.is() && xNameAccess->hasByName(m_sName))
245 {
246 xNameAccess->getByName(m_sName) >>= m_xObject;
247 }
248
249 if(m_xObject.is())
250 {
251 try
252 {
253 if(m_xObject->getPropertySetInfo()->hasPropertyByName(PROPERTY_FONT))
254 m_xObject->getPropertyValue(PROPERTY_FONT) >>= m_aFont;
255
256 // the result set may be already set with the datadescriptor
257 if ( !m_xResultSet.is() )
258 {
259 m_xResultSet.set( m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.sdb.RowSet", m_xContext), UNO_QUERY );
260 Reference< XPropertySet > xProp( m_xResultSet, UNO_QUERY_THROW );
261 xProp->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( m_xConnection.getTyped() ) );
262 xProp->setPropertyValue( PROPERTY_COMMAND_TYPE, makeAny( m_nCommandType ) );
263 xProp->setPropertyValue( PROPERTY_COMMAND, makeAny( m_sName ) );
264 Reference< XRowSet > xRowSet( xProp, UNO_QUERY );
265 xRowSet->execute();
266 }
267 if ( !m_xRow.is() && m_xResultSet.is() )
268 {
269 m_xRow.set( m_xResultSet, UNO_QUERY );
270 m_xRowLocate.set( m_xResultSet, UNO_QUERY );
271 m_xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(m_xRow,UNO_QUERY_THROW)->getMetaData();
272 Reference<XColumnsSupplier> xSup(m_xResultSet,UNO_QUERY_THROW);
273 m_xRowSetColumns.set(xSup->getColumns(),UNO_QUERY_THROW);
274 }
275 }
276 catch(Exception& )
277 {
278 m_xRow = nullptr;
279 m_xResultSetMetaData = nullptr;
280 ::comphelper::disposeComponent(m_xResultSet);
281 throw;
282 }
283 }
284 if ( m_aFont.Name.isEmpty() )
285 {
286 vcl::Font aApplicationFont = OutputDevice::GetDefaultFont(
287 DefaultFontType::SANS_UNICODE,
288 Application::GetSettings().GetUILanguageTag().getLanguageType(),
289 GetDefaultFontFlags::OnlyOne
290 );
291 m_aFont = VCLUnoHelper::CreateFontDescriptor( aApplicationFont );
292 }
293
294 m_bInInitialize = false;
295 }
296
Write()297 bool ODatabaseImportExport::Write()
298 {
299 if ( m_bNeedToReInitialize )
300 {
301 if ( !m_bInInitialize )
302 initialize();
303 }
304 return true;
305 }
306
Read()307 bool ODatabaseImportExport::Read()
308 {
309 if ( m_bNeedToReInitialize )
310 {
311 if ( !m_bInInitialize )
312 initialize();
313 }
314 return true;
315 }
316
Write()317 bool ORTFImportExport::Write()
318 {
319 ODatabaseImportExport::Write();
320 m_pStream->WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RTF );
321 m_pStream->WriteCharPtr(OOO_STRING_SVTOOLS_RTF_ANSI);
322 if (sal_uInt32 nCpg = rtl_getWindowsCodePageFromTextEncoding(m_eDestEnc); nCpg && nCpg != 65001)
323 {
324 m_pStream->WriteCharPtr(OOO_STRING_SVTOOLS_RTF_ANSICPG).WriteUInt32AsString(nCpg);
325 }
326 m_pStream->WriteCharPtr(SAL_NEWLINE_STRING);
327
328 bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
329 bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
330 bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
331 bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
332
333 ::Color aColor;
334 if(m_xObject.is())
335 m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
336
337 OString aFonts(OUStringToOString(m_aFont.Name, RTL_TEXTENCODING_MS_1252));
338 if (aFonts.isEmpty())
339 {
340 OUString aName = Application::GetSettings().GetStyleSettings().GetAppFont().GetFamilyName();
341 aFonts = OUStringToOString(aName, RTL_TEXTENCODING_MS_1252);
342 }
343
344 m_pStream->WriteCharPtr( "{\\fonttbl" );
345 if (!aFonts.isEmpty())
346 {
347 sal_Int32 nIdx{0};
348 sal_Int32 nTok{-1}; // to compensate pre-increment
349 do {
350 m_pStream->WriteCharPtr( "\\f" );
351 m_pStream->WriteInt32AsString(++nTok);
352 m_pStream->WriteCharPtr( "\\fcharset0\\fnil " );
353 m_pStream->WriteOString( aFonts.getToken(0, ';', nIdx) );
354 m_pStream->WriteChar( ';' );
355 } while (nIdx>=0);
356 }
357 m_pStream->WriteChar( '}' ) ;
358 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
359 // write the rtf color table
360 m_pStream->WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_COLORTBL ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RED );
361 m_pStream->WriteUInt32AsString(aColor.GetRed());
362 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_GREEN );
363 m_pStream->WriteUInt32AsString(aColor.GetGreen());
364 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_BLUE );
365 m_pStream->WriteUInt32AsString(aColor.GetBlue());
366
367 m_pStream->WriteCharPtr( ";\\red255\\green255\\blue255;\\red192\\green192\\blue192;}" )
368 .WriteCharPtr( SAL_NEWLINE_STRING );
369
370 static char const aCell1[] = "\\clbrdrl\\brdrs\\brdrcf0\\clbrdrt\\brdrs\\brdrcf0\\clbrdrb\\brdrs\\brdrcf0\\clbrdrr\\brdrs\\brdrcf0\\clshdng10000\\clcfpat2\\cellx";
371
372 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TROWD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRGAPH );
373 m_pStream->WriteInt32AsString(40);
374 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
375
376 if(m_xObject.is())
377 {
378 Reference<XColumnsSupplier> xColSup(m_xObject,UNO_QUERY);
379 Reference<XNameAccess> xColumns = xColSup->getColumns();
380 Sequence< OUString> aNames(xColumns->getElementNames());
381 const OUString* pIter = aNames.getConstArray();
382
383 sal_Int32 nCount = aNames.getLength();
384 bool bUseResultMetaData = false;
385 if ( !nCount )
386 {
387 nCount = m_xResultSetMetaData->getColumnCount();
388 bUseResultMetaData = true;
389 }
390
391 for( sal_Int32 i=1; i<=nCount; ++i )
392 {
393 m_pStream->WriteCharPtr( aCell1 );
394 m_pStream->WriteInt32AsString(i*CELL_X);
395 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
396 }
397
398 // column description
399 m_pStream->WriteChar( '{' ).WriteCharPtr( SAL_NEWLINE_STRING );
400 m_pStream->WriteCharPtr( "\\trrh-270\\pard\\intbl" );
401
402 std::unique_ptr<OString[]> pHorzChar(new OString[nCount]);
403
404 for ( sal_Int32 i=1; i <= nCount; ++i )
405 {
406 sal_Int32 nAlign = 0;
407 OUString sColumnName;
408 if ( bUseResultMetaData )
409 sColumnName = m_xResultSetMetaData->getColumnName(i);
410 else
411 {
412 sColumnName = *pIter;
413 Reference<XPropertySet> xColumn;
414 xColumns->getByName(sColumnName) >>= xColumn;
415 xColumn->getPropertyValue(PROPERTY_ALIGN) >>= nAlign;
416 ++pIter;
417 }
418
419 const char* pChar;
420 switch( nAlign )
421 {
422 case 1: pChar = OOO_STRING_SVTOOLS_RTF_QC; break;
423 case 2: pChar = OOO_STRING_SVTOOLS_RTF_QR; break;
424 case 0:
425 default:pChar = OOO_STRING_SVTOOLS_RTF_QL; break;
426 }
427
428 pHorzChar[i-1] = pChar; // to avoid to always rummage in the ITEMSET later on
429
430 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
431 m_pStream->WriteChar( '{' );
432 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_QC ); // column header always centered
433
434 if ( bBold ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B );
435 if ( bItalic ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I );
436 if ( bUnderline ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UL );
437 if ( bStrikeout ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STRIKE );
438
439 m_pStream->WriteCharPtr( "\\fs20\\f0\\cf0\\cb2" );
440 m_pStream->WriteChar( ' ' );
441 RTFOutFuncs::Out_String(*m_pStream, sColumnName, m_eDestEnc);
442
443 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELL );
444 m_pStream->WriteChar( '}' );
445 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
446 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PARD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_INTBL );
447 }
448
449 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ROW );
450 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING ).WriteChar( '}' );
451 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
452
453 sal_Int32 k=1;
454 sal_Int32 kk=0;
455 if ( m_aSelection.hasElements() )
456 {
457 const Any* pSelIter = m_aSelection.getConstArray();
458 const Any* pEnd = pSelIter + m_aSelection.getLength();
459
460 bool bContinue = true;
461 for( ; pSelIter != pEnd && bContinue; ++pSelIter )
462 {
463 if ( m_bBookmarkSelection )
464 {
465 bContinue = m_xRowLocate->moveToBookmark( *pSelIter );
466 }
467 else
468 {
469 sal_Int32 nPos = -1;
470 OSL_VERIFY( *pSelIter >>= nPos );
471 bContinue = ( m_xResultSet->absolute( nPos ) );
472 }
473
474 if ( bContinue )
475 appendRow( pHorzChar.get(), nCount, k, kk );
476 }
477 }
478 else
479 {
480 m_xResultSet->beforeFirst(); // set back before the first row
481 while(m_xResultSet->next())
482 {
483 appendRow(pHorzChar.get(),nCount,k,kk);
484 }
485 }
486 }
487
488 m_pStream->WriteChar( '}' ).WriteCharPtr( SAL_NEWLINE_STRING );
489 m_pStream->WriteUChar( 0 );
490 return ((*m_pStream).GetError() == ERRCODE_NONE);
491 }
492
appendRow(OString const * pHorzChar,sal_Int32 _nColumnCount,sal_Int32 & k,sal_Int32 & kk)493 void ORTFImportExport::appendRow(OString const * pHorzChar,sal_Int32 _nColumnCount,sal_Int32& k,sal_Int32& kk)
494 {
495 ++kk;
496 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TROWD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TRGAPH );
497 m_pStream->WriteInt32AsString(40);
498 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
499
500 static char const aCell2[] = "\\clbrdrl\\brdrs\\brdrcf2\\clbrdrt\\brdrs\\brdrcf2\\clbrdrb\\brdrs\\brdrcf2\\clbrdrr\\brdrs\\brdrcf2\\clshdng10000\\clcfpat1\\cellx";
501
502 for ( sal_Int32 i=1; i<=_nColumnCount; ++i )
503 {
504 m_pStream->WriteCharPtr( aCell2 );
505 m_pStream->WriteInt32AsString(i*CELL_X);
506 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
507 }
508
509 const bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
510 const bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
511 const bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
512 const bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
513 Reference< XRowSet > xRowSet(m_xRow,UNO_QUERY);
514
515 m_pStream->WriteChar( '{' );
516 m_pStream->WriteCharPtr( "\\trrh-270\\pard\\intbl" );
517 for ( sal_Int32 i=1; i <= _nColumnCount; ++i )
518 {
519 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
520 m_pStream->WriteChar( '{' );
521 m_pStream->WriteOString( pHorzChar[i-1] );
522
523 if ( bBold ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B );
524 if ( bItalic ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I );
525 if ( bUnderline ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UL );
526 if ( bStrikeout ) m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STRIKE );
527
528 m_pStream->WriteCharPtr( "\\fs20\\f1\\cf0\\cb1 " );
529
530 try
531 {
532 Reference<XPropertySet> xColumn(m_xRowSetColumns->getByIndex(i-1),UNO_QUERY_THROW);
533 dbtools::FormattedColumnValue aFormatedValue(m_xContext,xRowSet,xColumn);
534 OUString sValue = aFormatedValue.getFormattedValue();
535 if ( !sValue.isEmpty() )
536 RTFOutFuncs::Out_String(*m_pStream,sValue,m_eDestEnc);
537 }
538 catch (Exception&)
539 {
540 SAL_WARN("dbaccess.ui","RTF WRITE!");
541 }
542
543 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CELL );
544 m_pStream->WriteChar( '}' );
545 m_pStream->WriteCharPtr( SAL_NEWLINE_STRING );
546 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PARD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_INTBL );
547 }
548 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ROW ).WriteCharPtr( SAL_NEWLINE_STRING );
549 m_pStream->WriteChar( '}' );
550 ++k;
551 }
552
Read()553 bool ORTFImportExport::Read()
554 {
555 ODatabaseImportExport::Read();
556 SvParserState eState = SvParserState::Error;
557 if ( m_pStream )
558 {
559 tools::SvRef<ORTFReader> xReader(new ORTFReader((*m_pStream),m_xConnection,m_xFormatter,m_xContext));
560 if ( isCheckEnabled() )
561 xReader->enableCheckOnly();
562 eState = xReader->CallParser();
563 }
564
565 return eState != SvParserState::Error;
566 }
567
568 const sal_Int16 OHTMLImportExport::nCellSpacing = 0;
569 const char OHTMLImportExport::sIndentSource[nIndentMax+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
570
571 // Macros for HTML-Export
572 #define TAG_ON( tag ) HTMLOutFuncs::Out_AsciiTag( (*m_pStream), tag )
573 #define TAG_OFF( tag ) HTMLOutFuncs::Out_AsciiTag( (*m_pStream), tag, false )
574 #define OUT_LF() m_pStream->WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() )
575 #define TAG_ON_LF( tag ) (TAG_ON( tag ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() ))
576 #define TAG_OFF_LF( tag ) (TAG_OFF( tag ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() ))
577
OHTMLImportExport(const svx::ODataAccessDescriptor & _aDataDescriptor,const Reference<XComponentContext> & _rM,const Reference<css::util::XNumberFormatter> & _rxNumberF)578 OHTMLImportExport::OHTMLImportExport(const svx::ODataAccessDescriptor& _aDataDescriptor,
579 const Reference< XComponentContext >& _rM,
580 const Reference< css::util::XNumberFormatter >& _rxNumberF)
581 : ODatabaseImportExport(_aDataDescriptor,_rM,_rxNumberF)
582 ,m_nIndent(0)
583 #if OSL_DEBUG_LEVEL > 0
584 ,m_bCheckFont(false)
585 #endif
586 {
587 // set HTML configuration
588 SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
589 m_eDestEnc = rHtmlOptions.GetTextEncoding();
590 strncpy( sIndent, sIndentSource ,std::min(sizeof(sIndent),sizeof(sIndentSource)));
591 sIndent[0] = 0;
592 }
593
Write()594 bool OHTMLImportExport::Write()
595 {
596 ODatabaseImportExport::Write();
597 if(m_xObject.is())
598 {
599 m_pStream->WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype ).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype40 ).WriteChar( '>' ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( SAL_NEWLINE_STRING );
600 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_html );
601 WriteHeader();
602 OUT_LF();
603 WriteBody();
604 OUT_LF();
605 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_html );
606
607 return ((*m_pStream).GetError() == ERRCODE_NONE);
608 }
609 return false;
610 }
611
Read()612 bool OHTMLImportExport::Read()
613 {
614 ODatabaseImportExport::Read();
615 SvParserState eState = SvParserState::Error;
616 if ( m_pStream )
617 {
618 tools::SvRef<OHTMLReader> xReader(new OHTMLReader((*m_pStream),m_xConnection,m_xFormatter,m_xContext));
619 if ( isCheckEnabled() )
620 xReader->enableCheckOnly();
621 xReader->SetTableName(m_sDefaultTableName);
622 eState = xReader->CallParser();
623 }
624
625 return eState != SvParserState::Error;
626 }
627
WriteHeader()628 void OHTMLImportExport::WriteHeader()
629 {
630 uno::Reference<document::XDocumentProperties> xDocProps(
631 document::DocumentProperties::create( m_xContext ) );
632 if (xDocProps.is()) {
633 xDocProps->setTitle(m_sName);
634 }
635
636 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_head );
637
638 SfxFrameHTMLWriter::Out_DocInfo( (*m_pStream), OUString(),
639 xDocProps, sIndent, osl_getThreadTextEncoding() );
640 OUT_LF();
641 IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head );
642 }
643
WriteBody()644 void OHTMLImportExport::WriteBody()
645 {
646 IncIndent(1);
647 m_pStream->WriteCharPtr( "<" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_style ).WriteCharPtr( " " ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_type ).WriteCharPtr( "=\"text/css\">" );
648
649 m_pStream->WriteCharPtr( "<!-- " ); OUT_LF();
650 m_pStream->WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body ).WriteCharPtr( " { " ).WriteCharPtr( "font-family: " ).WriteChar( '"' ).WriteOString( OUStringToOString(m_aFont.Name, osl_getThreadTextEncoding()) ).WriteChar( '\"' );
651 // TODO : think about the encoding of the font name
652 m_pStream->WriteCharPtr( "; " ).WriteCharPtr( "font-size: " );
653 m_pStream->WriteInt32AsString(m_aFont.Height);
654 m_pStream->WriteChar( '}' );
655
656 OUT_LF();
657 m_pStream->WriteCharPtr( " -->" );
658 IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_style );
659 OUT_LF();
660
661 // default Textcolour black
662 m_pStream->WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body ).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_text ).WriteChar( '=' );
663 ::Color aColor;
664 if(m_xObject.is())
665 m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
666 HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
667
668 m_pStream->WriteCharPtr( " " OOO_STRING_SVTOOLS_HTML_O_bgcolor "=" );
669 HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
670
671 m_pStream->WriteChar( '>' ); OUT_LF();
672
673 WriteTables();
674
675 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_body );
676 }
677
WriteTables()678 void OHTMLImportExport::WriteTables()
679 {
680 OString aStrOut = OOO_STRING_SVTOOLS_HTML_table
681 " "
682 OOO_STRING_SVTOOLS_HTML_frame
683 "="
684 OOO_STRING_SVTOOLS_HTML_TF_void;
685
686 Sequence< OUString> aNames;
687 Reference<XNameAccess> xColumns;
688 bool bUseResultMetaData = false;
689 if(m_xObject.is())
690 {
691 Reference<XColumnsSupplier> xColSup(m_xObject,UNO_QUERY);
692 xColumns = xColSup->getColumns();
693 aNames = xColumns->getElementNames();
694 if ( !aNames.hasElements() )
695 {
696 sal_Int32 nCount = m_xResultSetMetaData->getColumnCount();
697 aNames.realloc(nCount);
698 for (sal_Int32 i= 0; i < nCount; ++i)
699 aNames[i] = m_xResultSetMetaData->getColumnName(i+1);
700 bUseResultMetaData = true;
701 }
702 }
703
704 aStrOut += " "
705 OOO_STRING_SVTOOLS_HTML_O_align
706 "="
707 OOO_STRING_SVTOOLS_HTML_AL_left
708 " "
709 OOO_STRING_SVTOOLS_HTML_O_cellspacing
710 "=" +
711 OString::number(nCellSpacing) +
712 " "
713 OOO_STRING_SVTOOLS_HTML_O_cols
714 "=" +
715 OString::number(aNames.getLength()) +
716 " "
717 OOO_STRING_SVTOOLS_HTML_O_border
718 "=1";
719
720 IncIndent(1);
721 TAG_ON( aStrOut.getStr() );
722
723 FontOn();
724
725 TAG_ON( OOO_STRING_SVTOOLS_HTML_caption );
726 TAG_ON( OOO_STRING_SVTOOLS_HTML_bold );
727
728 m_pStream->WriteOString( OUStringToOString(m_sName, osl_getThreadTextEncoding()) );
729 // TODO : think about the encoding of the name
730 TAG_OFF( OOO_STRING_SVTOOLS_HTML_bold );
731 TAG_OFF( OOO_STRING_SVTOOLS_HTML_caption );
732
733 FontOff();
734 OUT_LF();
735 // </FONT>
736
737 IncIndent(1);
738 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_thead );
739
740 IncIndent(1);
741 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
742
743 if(m_xObject.is())
744 {
745 std::unique_ptr<sal_Int32[]> pFormat(new sal_Int32[aNames.getLength()]);
746
747 std::unique_ptr<const char *[]> pHorJustify(new const char*[aNames.getLength()]);
748 std::unique_ptr<sal_Int32[]> pColWidth(new sal_Int32[aNames.getLength()]);
749
750 sal_Int32 nHeight = 0;
751 m_xObject->getPropertyValue(PROPERTY_ROW_HEIGHT) >>= nHeight;
752
753 // 1. writing the column description
754 const OUString* pIter = aNames.getConstArray();
755 const OUString* pEnd = pIter + aNames.getLength();
756
757 for( sal_Int32 i=0;pIter != pEnd; ++pIter,++i )
758 {
759 sal_Int32 nAlign = 0;
760 pFormat[i] = 0;
761 pColWidth[i] = 100;
762 if ( !bUseResultMetaData )
763 {
764 Reference<XPropertySet> xColumn;
765 xColumns->getByName(*pIter) >>= xColumn;
766 xColumn->getPropertyValue(PROPERTY_ALIGN) >>= nAlign;
767 pFormat[i] = ::comphelper::getINT32(xColumn->getPropertyValue(PROPERTY_FORMATKEY));
768 pColWidth[i] = ::comphelper::getINT32(xColumn->getPropertyValue(PROPERTY_WIDTH));
769 }
770
771 switch( nAlign )
772 {
773 case 1: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_center; break;
774 case 2: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_right; break;
775 default: pHorJustify[i] = OOO_STRING_SVTOOLS_HTML_AL_left; break;
776 }
777
778 if(i == aNames.getLength()-1)
779 IncIndent(-1);
780
781 WriteCell(pFormat[i],pColWidth[i],nHeight,pHorJustify[i],*pIter,OOO_STRING_SVTOOLS_HTML_tableheader);
782 }
783
784 IncIndent(-1);
785 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
786 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_thead );
787
788 IncIndent(1);
789 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tbody );
790
791 // 2. and now the data
792 Reference< XRowSet > xRowSet(m_xRow,UNO_QUERY);
793 sal_Int32 kk=0;
794 m_xResultSet->beforeFirst(); // set back before the first row
795 while(m_xResultSet->next())
796 {
797 IncIndent(1);
798 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
799
800 ++kk;
801 for(sal_Int32 i=1;i<=aNames.getLength();++i)
802 {
803 if(i == aNames.getLength())
804 IncIndent(-1);
805
806 OUString aValue;
807 try
808 {
809 Reference<XPropertySet> xColumn(m_xRowSetColumns->getByIndex(i-1),UNO_QUERY_THROW);
810 dbtools::FormattedColumnValue aFormatedValue(m_xContext,xRowSet,xColumn);
811 OUString sValue = aFormatedValue.getFormattedValue();
812 if (!sValue.isEmpty())
813 {
814 aValue = sValue;
815 }
816 }
817 catch( const Exception& )
818 {
819 DBG_UNHANDLED_EXCEPTION("dbaccess");
820 }
821 WriteCell(pFormat[i-1],pColWidth[i-1],nHeight,pHorJustify[i-1],aValue,OOO_STRING_SVTOOLS_HTML_tabledata);
822 }
823 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
824 }
825 }
826 else
827 {
828 IncIndent(-1);
829 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
830 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_thead );
831
832 IncIndent(1);
833 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tbody );
834 }
835
836 IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tbody );
837 IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_table );
838 }
839
WriteCell(sal_Int32 nFormat,sal_Int32 nWidthPixel,sal_Int32 nHeightPixel,const char * pChar,const OUString & rValue,const char * pHtmlTag)840 void OHTMLImportExport::WriteCell( sal_Int32 nFormat, sal_Int32 nWidthPixel, sal_Int32 nHeightPixel, const char* pChar,
841 const OUString& rValue, const char* pHtmlTag)
842 {
843 OString aStrTD = pHtmlTag;
844
845 nWidthPixel = nWidthPixel ? nWidthPixel : 86;
846 nHeightPixel = nHeightPixel ? nHeightPixel : 17;
847
848 // despite the <TABLE COLS=n> and <COL WIDTH=x> designation necessary,
849 // as Netscape is not paying attention to them.
850 // column width
851 aStrTD += " "
852 OOO_STRING_SVTOOLS_HTML_O_width
853 "=" +
854 OString::number(nWidthPixel) +
855 // line height
856 " "
857 OOO_STRING_SVTOOLS_HTML_O_height
858 "=" +
859 OString::number(nHeightPixel) +
860 " "
861 OOO_STRING_SVTOOLS_HTML_O_align
862 "=" +
863 pChar;
864
865 SvNumberFormatsSupplierObj* pSupplierImpl = m_xFormatter.is() ? comphelper::getUnoTunnelImplementation<SvNumberFormatsSupplierObj>(m_xFormatter->getNumberFormatsSupplier()) : nullptr;
866 SvNumberFormatter* pFormatter = pSupplierImpl ? pSupplierImpl->GetNumberFormatter() : nullptr;
867 if(pFormatter)
868 {
869 double fVal = 0.0;
870
871 try
872 {
873 fVal = m_xFormatter->convertStringToNumber(nFormat,rValue);
874 HTMLOutFuncs::CreateTableDataOptionsValNum(false, fVal,nFormat, *pFormatter);
875 }
876 catch(const Exception&)
877 {
878 HTMLOutFuncs::CreateTableDataOptionsValNum(false, fVal,nFormat, *pFormatter);
879 }
880 }
881
882 TAG_ON( aStrTD.getStr() );
883
884 FontOn();
885
886 bool bBold = ( css::awt::FontWeight::BOLD == m_aFont.Weight );
887 bool bItalic = ( css::awt::FontSlant_ITALIC == m_aFont.Slant );
888 bool bUnderline = ( css::awt::FontUnderline::NONE != m_aFont.Underline );
889 bool bStrikeout = ( css::awt::FontStrikeout::NONE != m_aFont.Strikeout );
890
891 if ( bBold ) TAG_ON( OOO_STRING_SVTOOLS_HTML_bold );
892 if ( bItalic ) TAG_ON( OOO_STRING_SVTOOLS_HTML_italic );
893 if ( bUnderline ) TAG_ON( OOO_STRING_SVTOOLS_HTML_underline );
894 if ( bStrikeout ) TAG_ON( OOO_STRING_SVTOOLS_HTML_strike );
895
896 if ( rValue.isEmpty() )
897 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak ); // no completely empty cell
898 else
899 HTMLOutFuncs::Out_String( (*m_pStream), rValue ,m_eDestEnc);
900
901 if ( bStrikeout ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_strike );
902 if ( bUnderline ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_underline );
903 if ( bItalic ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_italic );
904 if ( bBold ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_bold );
905
906 FontOff();
907
908 TAG_OFF_LF( pHtmlTag );
909 }
910
FontOn()911 void OHTMLImportExport::FontOn()
912 {
913 #if OSL_DEBUG_LEVEL > 0
914 m_bCheckFont = true;
915 #endif
916
917 // <FONT FACE="xxx">
918 OString aStrOut = "<"
919 OOO_STRING_SVTOOLS_HTML_font
920 " "
921 OOO_STRING_SVTOOLS_HTML_O_face
922 "="
923 "\"" +
924 OUStringToOString(m_aFont.Name,osl_getThreadTextEncoding()) +
925 // TODO : think about the encoding of the font name
926 "\""
927 " "
928 OOO_STRING_SVTOOLS_HTML_O_color
929 "=";
930 m_pStream->WriteOString( aStrOut );
931
932 ::Color aColor;
933 if(m_xObject.is())
934 m_xObject->getPropertyValue(PROPERTY_TEXTCOLOR) >>= aColor;
935
936 HTMLOutFuncs::Out_Color( (*m_pStream), aColor );
937 m_pStream->WriteCharPtr( ">" );
938 }
939
FontOff()940 inline void OHTMLImportExport::FontOff()
941 {
942 #if OSL_DEBUG_LEVEL > 0
943 OSL_ENSURE(m_bCheckFont,"No FontOn() called");
944 #endif
945 TAG_OFF( OOO_STRING_SVTOOLS_HTML_font );
946 #if OSL_DEBUG_LEVEL > 0
947 m_bCheckFont = false;
948 #endif
949 }
950
IncIndent(sal_Int16 nVal)951 void OHTMLImportExport::IncIndent( sal_Int16 nVal )
952 {
953 sIndent[m_nIndent] = '\t';
954 m_nIndent = m_nIndent + nVal;
955 if ( m_nIndent < 0 )
956 m_nIndent = 0;
957 else if ( m_nIndent > nIndentMax )
958 m_nIndent = nIndentMax;
959 sIndent[m_nIndent] = 0;
960 }
961
962 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
963