Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <com/sun/star/i18n/XBreakIterator.hpp>
30 : : #include <com/sun/star/i18n/ScriptType.hpp>
31 : : #include <sfx2/objsh.hxx>
32 : : #include <vcl/font.hxx>
33 : : #include <tools/urlobj.hxx>
34 : : #include <svl/itemset.hxx>
35 : : #include <svtools/ctrltool.hxx>
36 : : #include <svx/svdotext.hxx>
37 : : #include <editeng/outlobj.hxx>
38 : : #include "scitems.hxx"
39 : : #include <editeng/fhgtitem.hxx>
40 : : #include <editeng/flstitem.hxx>
41 : : #include <editeng/colritem.hxx>
42 : : #include <editeng/eeitem.hxx>
43 : : #include <editeng/flditem.hxx>
44 : : #include <editeng/escpitem.hxx>
45 : : #include <editeng/svxfont.hxx>
46 : :
47 : : #include "document.hxx"
48 : : #include "docpool.hxx"
49 : : #include "cell.hxx"
50 : : #include "editutil.hxx"
51 : : #include "patattr.hxx"
52 : : #include "xestyle.hxx"
53 : : #include "fprogressbar.hxx"
54 : : #include "xltracer.hxx"
55 : : #include "xecontent.hxx"
56 : : #include "xelink.hxx"
57 : : #include "xehelper.hxx"
58 : :
59 : : using ::rtl::OUString;
60 : : using ::com::sun::star::uno::Reference;
61 : : using ::com::sun::star::i18n::XBreakIterator;
62 : :
63 : : // Export progress bar ========================================================
64 : :
65 : 0 : XclExpProgressBar::XclExpProgressBar( const XclExpRoot& rRoot ) :
66 : : XclExpRoot( rRoot ),
67 [ # # ]: 0 : mxProgress( new ScfProgressBar( rRoot.GetDocShell(), STR_SAVE_DOC ) ),
68 : : mpSubProgress( 0 ),
69 : : mpSubRowCreate( 0 ),
70 : : mpSubRowFinal( 0 ),
71 : : mnSegRowFinal( SCF_INV_SEGMENT ),
72 [ # # ][ # # ]: 0 : mnRowCount( 0 )
[ # # ]
73 : : {
74 : 0 : }
75 : :
76 [ # # ]: 0 : XclExpProgressBar::~XclExpProgressBar()
77 : : {
78 [ # # ]: 0 : }
79 : :
80 : 0 : void XclExpProgressBar::Initialize()
81 : : {
82 : 0 : const ScDocument& rDoc = GetDoc();
83 : 0 : const XclExpTabInfo& rTabInfo = GetTabInfo();
84 : 0 : SCTAB nScTabCount = rTabInfo.GetScTabCount();
85 : :
86 : : // *** segment: creation of ROW records *** -------------------------------
87 : :
88 : 0 : sal_Int32 nSegRowCreate = mxProgress->AddSegment( 2000 );
89 : 0 : mpSubRowCreate = &mxProgress->GetSegmentProgressBar( nSegRowCreate );
90 : 0 : maSubSegRowCreate.resize( nScTabCount, SCF_INV_SEGMENT );
91 : :
92 [ # # ]: 0 : for( SCTAB nScTab = 0; nScTab < nScTabCount; ++nScTab )
93 : : {
94 [ # # ]: 0 : if( rTabInfo.IsExportTab( nScTab ) )
95 : : {
96 : : SCCOL nLastUsedScCol;
97 : : SCROW nLastUsedScRow;
98 [ # # ]: 0 : rDoc.GetTableArea( nScTab, nLastUsedScCol, nLastUsedScRow );
99 : 0 : sal_Size nSegSize = static_cast< sal_Size >( nLastUsedScRow + 1 );
100 [ # # ][ # # ]: 0 : maSubSegRowCreate[ nScTab ] = mpSubRowCreate->AddSegment( nSegSize );
101 : : }
102 : : }
103 : :
104 : : // *** segment: writing all ROW records *** -------------------------------
105 : :
106 : 0 : mnSegRowFinal = mxProgress->AddSegment( 1000 );
107 : : // sub progress bar and segment are created later in ActivateFinalRowsSegment()
108 : 0 : }
109 : :
110 : 0 : void XclExpProgressBar::IncRowRecordCount()
111 : : {
112 : 0 : ++mnRowCount;
113 : 0 : }
114 : :
115 : 0 : void XclExpProgressBar::ActivateCreateRowsSegment()
116 : : {
117 : : OSL_ENSURE( (0 <= GetCurrScTab()) && (GetCurrScTab() < GetTabInfo().GetScTabCount()),
118 : : "XclExpProgressBar::ActivateCreateRowsSegment - invalid sheet" );
119 : 0 : sal_Int32 nSeg = maSubSegRowCreate[ GetCurrScTab() ];
120 : : OSL_ENSURE( nSeg != SCF_INV_SEGMENT, "XclExpProgressBar::ActivateCreateRowsSegment - invalid segment" );
121 [ # # ]: 0 : if( nSeg != SCF_INV_SEGMENT )
122 : : {
123 : 0 : mpSubProgress = mpSubRowCreate;
124 : 0 : mpSubProgress->ActivateSegment( nSeg );
125 : : }
126 : : else
127 : 0 : mpSubProgress = 0;
128 : 0 : }
129 : :
130 : 0 : void XclExpProgressBar::ActivateFinalRowsSegment()
131 : : {
132 [ # # ][ # # ]: 0 : if( !mpSubRowFinal && (mnRowCount > 0) )
133 : : {
134 : 0 : mpSubRowFinal = &mxProgress->GetSegmentProgressBar( mnSegRowFinal );
135 : 0 : mpSubRowFinal->AddSegment( mnRowCount );
136 : : }
137 : 0 : mpSubProgress = mpSubRowFinal;
138 [ # # ]: 0 : if( mpSubProgress )
139 : 0 : mpSubProgress->Activate();
140 : 0 : }
141 : :
142 : 0 : void XclExpProgressBar::Progress()
143 : : {
144 [ # # ][ # # ]: 0 : if( mpSubProgress && !mpSubProgress->IsFull() )
[ # # ]
145 : 0 : mpSubProgress->Progress();
146 : 0 : }
147 : :
148 : : // Calc->Excel cell address/range conversion ==================================
149 : :
150 : : namespace {
151 : :
152 : : /** Fills the passed Excel address with the passed Calc cell coordinates without checking any limits. */
153 : 0 : inline void lclFillAddress( XclAddress& rXclPos, SCCOL nScCol, SCROW nScRow )
154 : : {
155 : 0 : rXclPos.mnCol = static_cast< sal_uInt16 >( nScCol );
156 : 0 : rXclPos.mnRow = static_cast< sal_uInt32 >( nScRow );
157 : 0 : }
158 : :
159 : : } // namespace
160 : :
161 : : // ----------------------------------------------------------------------------
162 : :
163 : 0 : XclExpAddressConverter::XclExpAddressConverter( const XclExpRoot& rRoot ) :
164 : 0 : XclAddressConverterBase( rRoot.GetTracer(), rRoot.GetXclMaxPos() )
165 : : {
166 : 0 : }
167 : :
168 : : // cell address ---------------------------------------------------------------
169 : :
170 : 0 : bool XclExpAddressConverter::CheckAddress( const ScAddress& rScPos, bool bWarn )
171 : : {
172 : : // ScAddress::operator<=() doesn't do what we want here
173 [ # # ][ # # ]: 0 : bool bValidCol = (0 <= rScPos.Col()) && (rScPos.Col() <= maMaxPos.Col());
174 [ # # ][ # # ]: 0 : bool bValidRow = (0 <= rScPos.Row()) && (rScPos.Row() <= maMaxPos.Row());
175 [ # # ][ # # ]: 0 : bool bValidTab = (0 <= rScPos.Tab()) && (rScPos.Tab() <= maMaxPos.Tab());
176 : :
177 [ # # ][ # # ]: 0 : bool bValid = bValidCol && bValidRow && bValidTab;
[ # # ]
178 [ # # ][ # # ]: 0 : if( !bValid && bWarn )
179 : : {
180 : 0 : mbColTrunc |= !bValidCol;
181 : 0 : mbRowTrunc |= !bValidRow;
182 : 0 : mbTabTrunc |= (rScPos.Tab() > maMaxPos.Tab()); // do not warn for deleted refs
183 : 0 : mrTracer.TraceInvalidAddress( rScPos, maMaxPos );
184 : : }
185 : 0 : return bValid;
186 : : }
187 : :
188 : 0 : bool XclExpAddressConverter::ConvertAddress( XclAddress& rXclPos,
189 : : const ScAddress& rScPos, bool bWarn )
190 : : {
191 : 0 : bool bValid = CheckAddress( rScPos, bWarn );
192 [ # # ]: 0 : if( bValid )
193 : 0 : lclFillAddress( rXclPos, rScPos.Col(), rScPos.Row() );
194 : 0 : return bValid;
195 : : }
196 : :
197 : 0 : XclAddress XclExpAddressConverter::CreateValidAddress( const ScAddress& rScPos, bool bWarn )
198 : : {
199 : 0 : XclAddress aXclPos( ScAddress::UNINITIALIZED );
200 [ # # ]: 0 : if( !ConvertAddress( aXclPos, rScPos, bWarn ) )
201 [ # # ][ # # ]: 0 : lclFillAddress( aXclPos, ::std::min( rScPos.Col(), maMaxPos.Col() ), ::std::min( rScPos.Row(), maMaxPos.Row() ) );
202 : 0 : return aXclPos;
203 : : }
204 : :
205 : : // cell range -----------------------------------------------------------------
206 : :
207 : 0 : bool XclExpAddressConverter::CheckRange( const ScRange& rScRange, bool bWarn )
208 : : {
209 [ # # ][ # # ]: 0 : return CheckAddress( rScRange.aStart, bWarn ) && CheckAddress( rScRange.aEnd, bWarn );
210 : : }
211 : :
212 : 0 : bool XclExpAddressConverter::ValidateRange( ScRange& rScRange, bool bWarn )
213 : : {
214 : 0 : rScRange.Justify();
215 : :
216 : : // check start position
217 : 0 : bool bValidStart = CheckAddress( rScRange.aStart, bWarn );
218 [ # # ]: 0 : if( bValidStart )
219 : : {
220 : : // check & correct end position
221 : 0 : ScAddress& rScEnd = rScRange.aEnd;
222 [ # # ]: 0 : if( !CheckAddress( rScEnd, bWarn ) )
223 : : {
224 [ # # ]: 0 : rScEnd.SetCol( ::std::min( rScEnd.Col(), maMaxPos.Col() ) );
225 [ # # ]: 0 : rScEnd.SetRow( ::std::min( rScEnd.Row(), maMaxPos.Row() ) );
226 [ # # ]: 0 : rScEnd.SetTab( ::std::min( rScEnd.Tab(), maMaxPos.Tab() ) );
227 : : }
228 : : }
229 : :
230 : 0 : return bValidStart;
231 : : }
232 : :
233 : 0 : bool XclExpAddressConverter::ConvertRange( XclRange& rXclRange,
234 : : const ScRange& rScRange, bool bWarn )
235 : : {
236 : : // check start position
237 : 0 : bool bValidStart = CheckAddress( rScRange.aStart, bWarn );
238 [ # # ]: 0 : if( bValidStart )
239 : : {
240 : 0 : lclFillAddress( rXclRange.maFirst, rScRange.aStart.Col(), rScRange.aStart.Row() );
241 : :
242 : : // check & correct end position
243 : 0 : SCCOL nScCol2 = rScRange.aEnd.Col();
244 : 0 : SCROW nScRow2 = rScRange.aEnd.Row();
245 [ # # ][ # # ]: 0 : if( !CheckAddress( rScRange.aEnd, bWarn ) )
246 : : {
247 [ # # ]: 0 : nScCol2 = ::std::min( nScCol2, maMaxPos.Col() );
248 [ # # ]: 0 : nScRow2 = ::std::min( nScRow2, maMaxPos.Row() );
249 : : }
250 : 0 : lclFillAddress( rXclRange.maLast, nScCol2, nScRow2 );
251 : : }
252 : 0 : return bValidStart;
253 : : }
254 : :
255 : : // cell range list ------------------------------------------------------------
256 : :
257 : 0 : void XclExpAddressConverter::ValidateRangeList( ScRangeList& rScRanges, bool bWarn )
258 : : {
259 [ # # ]: 0 : for ( size_t nRange = rScRanges.size(); nRange > 0; )
260 : : {
261 : 0 : ScRange* pScRange = rScRanges[ --nRange ];
262 [ # # ]: 0 : if( !CheckRange( *pScRange, bWarn ) )
263 : 0 : delete rScRanges.Remove(nRange);
264 : : }
265 : 0 : }
266 : :
267 : 0 : void XclExpAddressConverter::ConvertRangeList( XclRangeList& rXclRanges,
268 : : const ScRangeList& rScRanges, bool bWarn )
269 : : {
270 : 0 : rXclRanges.clear();
271 [ # # ]: 0 : for( size_t nPos = 0, nCount = rScRanges.size(); nPos < nCount; ++nPos )
272 : : {
273 [ # # ]: 0 : if( const ScRange* pScRange = rScRanges[ nPos ] )
274 : : {
275 : 0 : XclRange aXclRange( ScAddress::UNINITIALIZED );
276 [ # # ][ # # ]: 0 : if( ConvertRange( aXclRange, *pScRange, bWarn ) )
277 [ # # ]: 0 : rXclRanges.push_back( aXclRange );
278 : : }
279 : : }
280 : 0 : }
281 : :
282 : : // EditEngine->String conversion ==============================================
283 : :
284 : : namespace {
285 : :
286 : 0 : rtl::OUString lclGetUrlRepresentation( const SvxURLField& rUrlField )
287 : : {
288 : 0 : const rtl::OUString& aRepr = rUrlField.GetRepresentation();
289 : : // no representation -> use URL
290 [ # # ]: 0 : return aRepr.isEmpty() ? rUrlField.GetURL() : aRepr;
291 : : }
292 : :
293 : : } // namespace
294 : :
295 : : // ----------------------------------------------------------------------------
296 : :
297 : 0 : XclExpHyperlinkHelper::XclExpHyperlinkHelper( const XclExpRoot& rRoot, const ScAddress& rScPos ) :
298 : : XclExpRoot( rRoot ),
299 : : maScPos( rScPos ),
300 [ # # ][ # # ]: 0 : mbMultipleUrls( false )
301 : : {
302 : 0 : }
303 : :
304 [ # # ][ # # ]: 0 : XclExpHyperlinkHelper::~XclExpHyperlinkHelper()
305 : : {
306 [ # # ]: 0 : }
307 : :
308 : 0 : rtl::OUString XclExpHyperlinkHelper::ProcessUrlField( const SvxURLField& rUrlField )
309 : : {
310 : 0 : rtl::OUString aUrlRepr;
311 : :
312 [ # # ]: 0 : if( GetBiff() == EXC_BIFF8 ) // no HLINK records in BIFF2-BIFF7
313 : : {
314 : : // there was/is already a HLINK record
315 : 0 : mbMultipleUrls = mxLinkRec;
316 : :
317 [ # # ][ # # ]: 0 : mxLinkRec.reset( new XclExpHyperlink( GetRoot(), rUrlField, maScPos ) );
[ # # ]
318 : :
319 [ # # ][ # # ]: 0 : if( const String* pRepr = mxLinkRec->GetRepr() )
320 [ # # ]: 0 : aUrlRepr = *pRepr;
321 : :
322 : : // add URL to note text
323 [ # # ][ # # ]: 0 : ScGlobal::AddToken( maUrlList, rUrlField.GetURL(), '\n' );
[ # # ]
324 : : }
325 : :
326 : : // no hyperlink representation from Excel HLINK record -> use it from text field
327 [ # # ]: 0 : return aUrlRepr.isEmpty() ? lclGetUrlRepresentation(rUrlField) : aUrlRepr;
328 : : }
329 : :
330 : 0 : bool XclExpHyperlinkHelper::HasLinkRecord() const
331 : : {
332 [ # # ][ # # ]: 0 : return !mbMultipleUrls && mxLinkRec;
333 : : }
334 : :
335 : 0 : XclExpHyperlinkHelper::XclExpHyperlinkRef XclExpHyperlinkHelper::GetLinkRecord()
336 : : {
337 [ # # ]: 0 : if( HasLinkRecord() )
338 : 0 : return mxLinkRec;
339 : 0 : return XclExpHyperlinkRef();
340 : : }
341 : :
342 : : // ----------------------------------------------------------------------------
343 : :
344 : : namespace {
345 : :
346 : : /** Creates a new formatted string from the passed unformatted string.
347 : :
348 : : Creates a Unicode string or a byte string, depending on the current BIFF
349 : : version contained in the passed XclExpRoot object. May create a formatted
350 : : string object, if the text contains different script types.
351 : :
352 : : @param pCellAttr
353 : : Cell attributes used for font formatting.
354 : : @param nFlags
355 : : Modifiers for string export.
356 : : @param nMaxLen
357 : : The maximum number of characters to store in this string.
358 : : @return
359 : : The new string object.
360 : : */
361 : 0 : XclExpStringRef lclCreateFormattedString(
362 : : const XclExpRoot& rRoot, const String& rText, const ScPatternAttr* pCellAttr,
363 : : XclStrFlags nFlags, sal_uInt16 nMaxLen )
364 : : {
365 : : /* Create an empty Excel string object with correctly initialized BIFF mode,
366 : : because this function only uses Append() functions that require this. */
367 [ # # ][ # # ]: 0 : XclExpStringRef xString = XclExpStringHelper::CreateString( rRoot, EMPTY_STRING, nFlags, nMaxLen );
368 : :
369 : : // script type handling
370 [ # # ]: 0 : Reference< XBreakIterator > xBreakIt = rRoot.GetDoc().GetBreakIterator();
371 : : namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
372 : : // #i63255# get script type for leading weak characters
373 [ # # ]: 0 : sal_Int16 nLastScript = XclExpStringHelper::GetLeadingScriptType( rRoot, rText );
374 : :
375 : : // font buffer and cell item set
376 [ # # ]: 0 : XclExpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
377 [ # # ][ # # ]: 0 : const SfxItemSet& rItemSet = pCellAttr ? pCellAttr->GetItemSet() : rRoot.GetDoc().GetDefPattern()->GetItemSet();
378 : :
379 : : // process all script portions
380 [ # # ]: 0 : OUString aOUText( rText );
381 : 0 : sal_Int32 nPortionPos = 0;
382 : 0 : sal_Int32 nTextLen = aOUText.getLength();
383 [ # # ]: 0 : while( nPortionPos < nTextLen )
384 : : {
385 : : // get script type and end position of next script portion
386 [ # # ][ # # ]: 0 : sal_Int16 nScript = xBreakIt->getScriptType( aOUText, nPortionPos );
387 [ # # ][ # # ]: 0 : sal_Int32 nPortionEnd = xBreakIt->endOfScript( aOUText, nPortionPos, nScript );
388 : :
389 : : // reuse previous script for following weak portions
390 [ # # ]: 0 : if( nScript == ApiScriptType::WEAK )
391 : 0 : nScript = nLastScript;
392 : :
393 : : // construct font from current text portion
394 [ # # ][ # # ]: 0 : SvxFont aFont( XclExpFontHelper::GetFontFromItemSet( rRoot, rItemSet, nScript ) );
[ # # ]
395 : :
396 : : // Excel start position of this portion
397 : 0 : sal_uInt16 nXclPortionStart = xString->Len();
398 : : // add portion text to Excel string
399 [ # # ][ # # ]: 0 : XclExpStringHelper::AppendString( *xString, rRoot, aOUText.copy( nPortionPos, nPortionEnd - nPortionPos ) );
[ # # ]
400 [ # # ]: 0 : if( nXclPortionStart < xString->Len() )
401 : : {
402 : : // insert font into buffer
403 [ # # ]: 0 : sal_uInt16 nFontIdx = rFontBuffer.Insert( aFont, EXC_COLOR_CELLTEXT );
404 : : // insert font index into format run vector
405 [ # # ]: 0 : xString->AppendFormat( nXclPortionStart, nFontIdx );
406 : : }
407 : :
408 : : // go to next script portion
409 : 0 : nLastScript = nScript;
410 : 0 : nPortionPos = nPortionEnd;
411 [ # # ]: 0 : }
412 : :
413 : 0 : return xString;
414 : : }
415 : :
416 : : /** Creates a new formatted string from an edit engine text object.
417 : :
418 : : Creates a Unicode string or a byte string, depending on the current BIFF
419 : : version contained in the passed XclExpRoot object.
420 : :
421 : : @param rEE
422 : : The edit engine in use. The text object must already be set.
423 : : @param nFlags
424 : : Modifiers for string export.
425 : : @param nMaxLen
426 : : The maximum number of characters to store in this string.
427 : : @return
428 : : The new string object.
429 : : */
430 : 0 : XclExpStringRef lclCreateFormattedString(
431 : : const XclExpRoot& rRoot, EditEngine& rEE, XclExpHyperlinkHelper* pLinkHelper,
432 : : XclStrFlags nFlags, sal_uInt16 nMaxLen )
433 : : {
434 : : /* Create an empty Excel string object with correctly initialized BIFF mode,
435 : : because this function only uses Append() functions that require this. */
436 [ # # ][ # # ]: 0 : XclExpStringRef xString = XclExpStringHelper::CreateString( rRoot, EMPTY_STRING, nFlags, nMaxLen );
437 : :
438 : : // font buffer and helper item set for edit engine -> Calc item conversion
439 [ # # ]: 0 : XclExpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
440 [ # # ][ # # ]: 0 : SfxItemSet aItemSet( *rRoot.GetDoc().GetPool(), ATTR_PATTERN_START, ATTR_PATTERN_END );
441 : :
442 : : // script type handling
443 [ # # ]: 0 : Reference< XBreakIterator > xBreakIt = rRoot.GetDoc().GetBreakIterator();
444 : : namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
445 : : // #i63255# get script type for leading weak characters
446 [ # # ][ # # ]: 0 : sal_Int16 nLastScript = XclExpStringHelper::GetLeadingScriptType( rRoot, rEE.GetText() );
[ # # ]
447 : :
448 : : // process all paragraphs
449 [ # # ]: 0 : sal_uInt16 nParaCount = rEE.GetParagraphCount();
450 [ # # ]: 0 : for( sal_uInt16 nPara = 0; nPara < nParaCount; ++nPara )
451 : : {
452 : 0 : ESelection aSel( nPara, 0 );
453 [ # # ]: 0 : String aParaText( rEE.GetText( nPara ) );
454 : :
455 [ # # ]: 0 : std::vector<sal_uInt16> aPosList;
456 [ # # ]: 0 : rEE.GetPortions( nPara, aPosList );
457 : :
458 : : // process all portions in the paragraph
459 [ # # ][ # # ]: 0 : for( std::vector<sal_uInt16>::const_iterator it(aPosList.begin()); it != aPosList.end(); ++it )
[ # # ][ # # ]
460 : : {
461 [ # # ]: 0 : aSel.nEndPos = static_cast< xub_StrLen >( *it );
462 [ # # ]: 0 : String aXclPortionText( aParaText, aSel.nStartPos, aSel.nEndPos - aSel.nStartPos );
463 : :
464 [ # # ]: 0 : aItemSet.ClearItem();
465 [ # # ]: 0 : SfxItemSet aEditSet( rEE.GetAttribs( aSel ) );
466 [ # # ]: 0 : ScPatternAttr::GetFromEditItemSet( aItemSet, aEditSet );
467 : :
468 : : // get escapement value
469 [ # # ]: 0 : short nEsc = GETITEM( aEditSet, SvxEscapementItem, EE_CHAR_ESCAPEMENT ).GetEsc();
470 : :
471 : : // process text fields
472 : 0 : bool bIsHyperlink = false;
473 [ # # ]: 0 : if( aSel.nStartPos + 1 == aSel.nEndPos )
474 : : {
475 : : // test if the character is a text field
476 : : const SfxPoolItem* pItem;
477 [ # # ][ # # ]: 0 : if( aEditSet.GetItemState( EE_FEATURE_FIELD, false, &pItem ) == SFX_ITEM_SET )
478 : : {
479 : 0 : const SvxFieldData* pField = static_cast< const SvxFieldItem* >( pItem )->GetField();
480 [ # # ][ # # ]: 0 : if( const SvxURLField* pUrlField = PTR_CAST( SvxURLField, pField ) )
[ # # ][ # # ]
[ # # ]
481 : : {
482 : : // convert URL field to string representation
483 : : aXclPortionText = pLinkHelper ?
484 : : pLinkHelper->ProcessUrlField( *pUrlField ) :
485 [ # # ][ # # ]: 0 : lclGetUrlRepresentation( *pUrlField );
[ # # ]
486 : 0 : bIsHyperlink = true;
487 : : }
488 : : else
489 : : {
490 : : OSL_FAIL( "lclCreateFormattedString - unknown text field" );
491 [ # # ]: 0 : aXclPortionText.Erase();
492 : : }
493 : : }
494 : : }
495 : :
496 : : // Excel start position of this portion
497 : 0 : sal_uInt16 nXclPortionStart = xString->Len();
498 : : // add portion text to Excel string
499 [ # # ]: 0 : XclExpStringHelper::AppendString( *xString, rRoot, aXclPortionText );
500 [ # # ][ # # ]: 0 : if( (nXclPortionStart < xString->Len()) || (aParaText.Len() == 0) )
[ # # ]
501 : : {
502 : : /* Construct font from current edit engine text portion. Edit engine
503 : : creates different portions for different script types, no need to loop. */
504 [ # # ][ # # ]: 0 : sal_Int16 nScript = xBreakIt->getScriptType( aXclPortionText, 0 );
[ # # ]
505 [ # # ]: 0 : if( nScript == ApiScriptType::WEAK )
506 : 0 : nScript = nLastScript;
507 [ # # ][ # # ]: 0 : SvxFont aFont( XclExpFontHelper::GetFontFromItemSet( rRoot, aItemSet, nScript ) );
[ # # ]
508 : 0 : nLastScript = nScript;
509 : :
510 : : // add escapement
511 : 0 : aFont.SetEscapement( nEsc );
512 : : // modify automatic font color for hyperlinks
513 [ # # ][ # # ]: 0 : if( bIsHyperlink && (GETITEM( aItemSet, SvxColorItem, ATTR_FONT_COLOR ).GetValue().GetColor() == COL_AUTO) )
[ # # ][ # # ]
514 [ # # ]: 0 : aFont.SetColor( Color( COL_LIGHTBLUE ) );
515 : :
516 : : // insert font into buffer
517 [ # # ]: 0 : sal_uInt16 nFontIdx = rFontBuffer.Insert( aFont, EXC_COLOR_CELLTEXT );
518 : : // insert font index into format run vector
519 [ # # ][ # # ]: 0 : xString->AppendFormat( nXclPortionStart, nFontIdx );
520 : : }
521 : :
522 : 0 : aSel.nStartPos = aSel.nEndPos;
523 [ # # ][ # # ]: 0 : }
524 : :
525 : : // add trailing newline (important for correct character index calculation)
526 [ # # ]: 0 : if( nPara + 1 < nParaCount )
527 [ # # ]: 0 : XclExpStringHelper::AppendChar( *xString, rRoot, '\n' );
528 [ # # ]: 0 : }
529 : :
530 [ # # ]: 0 : return xString;
531 : : }
532 : :
533 : : } // namespace
534 : :
535 : : // ----------------------------------------------------------------------------
536 : :
537 : 0 : XclExpStringRef XclExpStringHelper::CreateString(
538 : : const XclExpRoot& rRoot, const String& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen )
539 : : {
540 [ # # ][ # # ]: 0 : XclExpStringRef xString( new XclExpString );
541 [ # # ]: 0 : if( rRoot.GetBiff() == EXC_BIFF8 )
542 [ # # ]: 0 : xString->Assign( rString, nFlags, nMaxLen );
543 : : else
544 [ # # ]: 0 : xString->AssignByte( rString, rRoot.GetTextEncoding(), nFlags, nMaxLen );
545 : 0 : return xString;
546 : : }
547 : :
548 : 0 : XclExpStringRef XclExpStringHelper::CreateString(
549 : : const XclExpRoot& rRoot, sal_Unicode cChar, XclStrFlags nFlags, sal_uInt16 nMaxLen )
550 : : {
551 : 0 : XclExpStringRef xString = CreateString( rRoot, EMPTY_STRING, nFlags, nMaxLen );
552 [ # # ]: 0 : AppendChar( *xString, rRoot, cChar );
553 : 0 : return xString;
554 : : }
555 : :
556 : 0 : void XclExpStringHelper::AppendString( XclExpString& rXclString, const XclExpRoot& rRoot, const String& rString )
557 : : {
558 [ # # ]: 0 : if( rRoot.GetBiff() == EXC_BIFF8 )
559 : 0 : rXclString.Append( rString );
560 : : else
561 : 0 : rXclString.AppendByte( rString, rRoot.GetTextEncoding() );
562 : 0 : }
563 : :
564 : 0 : void XclExpStringHelper::AppendChar( XclExpString& rXclString, const XclExpRoot& rRoot, sal_Unicode cChar )
565 : : {
566 [ # # ]: 0 : if( rRoot.GetBiff() == EXC_BIFF8 )
567 [ # # ][ # # ]: 0 : rXclString.Append( rtl::OUString(cChar) );
[ # # ]
568 : : else
569 : 0 : rXclString.AppendByte( cChar, rRoot.GetTextEncoding() );
570 : 0 : }
571 : :
572 : 0 : XclExpStringRef XclExpStringHelper::CreateCellString(
573 : : const XclExpRoot& rRoot, const ScStringCell& rStringCell, const ScPatternAttr* pCellAttr,
574 : : XclStrFlags nFlags, sal_uInt16 nMaxLen )
575 : : {
576 : 0 : rtl::OUString aCellText = rStringCell.GetString();
577 [ # # ][ # # ]: 0 : return lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
[ # # ]
578 : : }
579 : :
580 : 0 : XclExpStringRef XclExpStringHelper::CreateCellString(
581 : : const XclExpRoot& rRoot, const ScEditCell& rEditCell, const ScPatternAttr* pCellAttr,
582 : : XclExpHyperlinkHelper& rLinkHelper, XclStrFlags nFlags, sal_uInt16 nMaxLen )
583 : : {
584 : 0 : XclExpStringRef xString;
585 [ # # ]: 0 : if( const EditTextObject* pEditObj = rEditCell.GetData() )
586 : : {
587 : : // formatted cell
588 [ # # ]: 0 : ScEditEngineDefaulter& rEE = rRoot.GetEditEngine();
589 [ # # ]: 0 : sal_Bool bOldUpdateMode = rEE.GetUpdateMode();
590 [ # # ]: 0 : rEE.SetUpdateMode( sal_True );
591 : : // default items
592 [ # # ][ # # ]: 0 : const SfxItemSet& rItemSet = pCellAttr ? pCellAttr->GetItemSet() : rRoot.GetDoc().GetDefPattern()->GetItemSet();
593 [ # # ][ # # ]: 0 : SfxItemSet* pEEItemSet = new SfxItemSet( rEE.GetEmptyItemSet() );
[ # # ]
594 [ # # ]: 0 : ScPatternAttr::FillToEditItemSet( *pEEItemSet, rItemSet );
595 [ # # ]: 0 : rEE.SetDefaults( pEEItemSet ); // edit engine takes ownership
596 : : // create the string
597 [ # # ]: 0 : rEE.SetText( *pEditObj );
598 [ # # ][ # # ]: 0 : xString = lclCreateFormattedString( rRoot, rEE, &rLinkHelper, nFlags, nMaxLen );
[ # # ]
599 [ # # ]: 0 : rEE.SetUpdateMode( bOldUpdateMode );
600 : : }
601 : : else
602 : : {
603 : : // unformatted cell
604 [ # # ][ # # ]: 0 : String aCellText = rEditCell.GetString();
605 [ # # ][ # # ]: 0 : xString = lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
[ # # ][ # # ]
606 : : }
607 : 0 : return xString;
608 : : }
609 : :
610 : 0 : XclExpStringRef XclExpStringHelper::CreateString(
611 : : const XclExpRoot& rRoot, const SdrTextObj& rTextObj,
612 : : XclStrFlags nFlags, sal_uInt16 nMaxLen )
613 : : {
614 : 0 : XclExpStringRef xString;
615 [ # # ][ # # ]: 0 : if( const OutlinerParaObject* pParaObj = rTextObj.GetOutlinerParaObject() )
616 : : {
617 [ # # ]: 0 : EditEngine& rEE = rRoot.GetDrawEditEngine();
618 [ # # ]: 0 : sal_Bool bOldUpdateMode = rEE.GetUpdateMode();
619 [ # # ]: 0 : rEE.SetUpdateMode( sal_True );
620 : : // create the string
621 [ # # ][ # # ]: 0 : rEE.SetText( pParaObj->GetTextObject() );
622 [ # # ][ # # ]: 0 : xString = lclCreateFormattedString( rRoot, rEE, 0, nFlags, nMaxLen );
[ # # ]
623 [ # # ]: 0 : rEE.SetUpdateMode( bOldUpdateMode );
624 : : // limit formats - TODO: BIFF dependent
625 [ # # ]: 0 : if( !xString->IsEmpty() )
626 : : {
627 [ # # ]: 0 : xString->LimitFormatCount( EXC_MAXRECSIZE_BIFF8 / 8 - 1 );
628 [ # # ]: 0 : xString->AppendTrailingFormat( EXC_FONT_APP );
629 : : }
630 : : }
631 : : else
632 : : {
633 : : OSL_FAIL( "XclExpStringHelper::CreateString - textbox without para object" );
634 : : // create BIFF dependent empty Excel string
635 [ # # ][ # # ]: 0 : xString = CreateString( rRoot, EMPTY_STRING, nFlags, nMaxLen );
[ # # ][ # # ]
636 : : }
637 : 0 : return xString;
638 : : }
639 : :
640 : 0 : XclExpStringRef XclExpStringHelper::CreateString(
641 : : const XclExpRoot& rRoot, const EditTextObject& rEditObj,
642 : : XclStrFlags nFlags, sal_uInt16 nMaxLen )
643 : : {
644 : 0 : XclExpStringRef xString;
645 [ # # ]: 0 : EditEngine& rEE = rRoot.GetDrawEditEngine();
646 [ # # ]: 0 : sal_Bool bOldUpdateMode = rEE.GetUpdateMode();
647 [ # # ]: 0 : rEE.SetUpdateMode( sal_True );
648 [ # # ]: 0 : rEE.SetText( rEditObj );
649 [ # # ][ # # ]: 0 : xString = lclCreateFormattedString( rRoot, rEE, 0, nFlags, nMaxLen );
[ # # ]
650 [ # # ]: 0 : rEE.SetUpdateMode( bOldUpdateMode );
651 : : // limit formats - TODO: BIFF dependent
652 [ # # ]: 0 : if( !xString->IsEmpty() )
653 : : {
654 [ # # ]: 0 : xString->LimitFormatCount( EXC_MAXRECSIZE_BIFF8 / 8 - 1 );
655 [ # # ]: 0 : xString->AppendTrailingFormat( EXC_FONT_APP );
656 : : }
657 : 0 : return xString;
658 : : }
659 : :
660 : 0 : sal_Int16 XclExpStringHelper::GetLeadingScriptType( const XclExpRoot& rRoot, const String& rString )
661 : : {
662 : : namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
663 [ # # ]: 0 : Reference< XBreakIterator > xBreakIt = rRoot.GetDoc().GetBreakIterator();
664 [ # # ]: 0 : OUString aOUString( rString );
665 : 0 : sal_Int32 nStrPos = 0;
666 : 0 : sal_Int32 nStrLen = aOUString.getLength();
667 : 0 : sal_Int16 nScript = ApiScriptType::WEAK;
668 [ # # ][ # # ]: 0 : while( (nStrPos < nStrLen) && (nScript == ApiScriptType::WEAK) )
[ # # ]
669 : : {
670 [ # # ][ # # ]: 0 : nScript = xBreakIt->getScriptType( aOUString, nStrPos );
671 [ # # ][ # # ]: 0 : nStrPos = xBreakIt->endOfScript( aOUString, nStrPos, nScript );
672 : : }
673 [ # # ]: 0 : return (nScript == ApiScriptType::WEAK) ? rRoot.GetDefApiScript() : nScript;
674 : : }
675 : :
676 : : // Header/footer conversion ===================================================
677 : :
678 : 0 : XclExpHFConverter::XclExpHFConverter( const XclExpRoot& rRoot ) :
679 : : XclExpRoot( rRoot ),
680 [ # # ]: 0 : mrEE( rRoot.GetHFEditEngine() ),
681 [ # # ]: 0 : mnTotalHeight( 0 )
682 : : {
683 : 0 : }
684 : :
685 : 0 : void XclExpHFConverter::GenerateString(
686 : : const EditTextObject* pLeftObj,
687 : : const EditTextObject* pCenterObj,
688 : : const EditTextObject* pRightObj )
689 : : {
690 : 0 : maHFString.Erase();
691 : 0 : mnTotalHeight = 0;
692 : 0 : AppendPortion( pLeftObj, 'L' );
693 : 0 : AppendPortion( pCenterObj, 'C' );
694 : 0 : AppendPortion( pRightObj, 'R' );
695 : 0 : }
696 : :
697 : 0 : void XclExpHFConverter::AppendPortion( const EditTextObject* pTextObj, sal_Unicode cPortionCode )
698 : : {
699 [ # # ]: 0 : if( !pTextObj ) return;
700 : :
701 [ # # ]: 0 : String aText;
702 : 0 : sal_Int32 nHeight = 0;
703 [ # # ][ # # ]: 0 : SfxItemSet aItemSet( *GetDoc().GetPool(), ATTR_PATTERN_START, ATTR_PATTERN_END );
704 : :
705 : : // edit engine
706 [ # # ]: 0 : sal_Bool bOldUpdateMode = mrEE.GetUpdateMode();
707 [ # # ]: 0 : mrEE.SetUpdateMode( sal_True );
708 [ # # ]: 0 : mrEE.SetText( *pTextObj );
709 : :
710 : : // font information
711 [ # # ][ # # ]: 0 : XclFontData aFontData, aNewData;
712 [ # # ][ # # ]: 0 : if( const XclExpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) )
[ # # ]
713 : : {
714 [ # # ]: 0 : aFontData = pFirstFont->GetFontData();
715 : 0 : (aFontData.mnHeight += 10) /= 20; // using pt here, not twips
716 : : }
717 : : else
718 : 0 : aFontData.mnHeight = 10;
719 : :
720 : 0 : const FontList* pFontList = 0;
721 [ # # ][ # # ]: 0 : if( SfxObjectShell* pDocShell = GetDocShell() )
722 : : {
723 [ # # ]: 0 : if( const SvxFontListItem* pInfoItem = static_cast< const SvxFontListItem* >(
724 [ # # ]: 0 : pDocShell->GetItem( SID_ATTR_CHAR_FONTLIST ) ) )
725 : 0 : pFontList = pInfoItem->GetFontList();
726 : : }
727 : :
728 [ # # ]: 0 : sal_uInt16 nParaCount = mrEE.GetParagraphCount();
729 [ # # ]: 0 : for( sal_uInt16 nPara = 0; nPara < nParaCount; ++nPara )
730 : : {
731 : 0 : ESelection aSel( nPara, 0 );
732 [ # # ]: 0 : String aParaText;
733 : 0 : sal_Int32 nParaHeight = 0;
734 [ # # ]: 0 : std::vector<sal_uInt16> aPosList;
735 [ # # ]: 0 : mrEE.GetPortions( nPara, aPosList );
736 : :
737 [ # # ][ # # ]: 0 : for( std::vector<sal_uInt16>::const_iterator it( aPosList.begin() ); it != aPosList.end(); ++it )
[ # # ][ # # ]
738 : : {
739 [ # # ]: 0 : aSel.nEndPos = static_cast< xub_StrLen >( *it );
740 [ # # ]: 0 : if( aSel.nStartPos < aSel.nEndPos )
741 : : {
742 : :
743 : : // --- font attributes ---
744 : :
745 [ # # ]: 0 : Font aFont;
746 [ # # ]: 0 : aItemSet.ClearItem();
747 [ # # ]: 0 : SfxItemSet aEditSet( mrEE.GetAttribs( aSel ) );
748 [ # # ]: 0 : ScPatternAttr::GetFromEditItemSet( aItemSet, aEditSet );
749 [ # # ]: 0 : ScPatternAttr::GetFont( aFont, aItemSet, SC_AUTOCOL_RAW );
750 : :
751 : : // font name and style
752 [ # # ][ # # ]: 0 : aNewData.maName = XclTools::GetXclFontName( aFont.GetName() );
[ # # ][ # # ]
753 [ # # ][ # # ]: 0 : aNewData.mnWeight = (aFont.GetWeight() > WEIGHT_NORMAL) ? EXC_FONTWGHT_BOLD : EXC_FONTWGHT_NORMAL;
754 [ # # ]: 0 : aNewData.mbItalic = (aFont.GetItalic() != ITALIC_NONE);
755 [ # # ]: 0 : bool bNewFont = !(aFontData.maName == aNewData.maName);
756 : : bool bNewStyle = (aFontData.mnWeight != aNewData.mnWeight) ||
757 [ # # ][ # # ]: 0 : (aFontData.mbItalic != aNewData.mbItalic);
758 [ # # ][ # # ]: 0 : if( bNewFont || (bNewStyle && pFontList) )
[ # # ]
759 : : {
760 [ # # ][ # # ]: 0 : aParaText.AppendAscii( "&\"" ).Append( aNewData.maName );
761 [ # # ]: 0 : if( pFontList )
762 : : {
763 : : FontInfo aFontInfo( pFontList->Get(
764 : : aNewData.maName,
765 : : (aNewData.mnWeight > EXC_FONTWGHT_NORMAL) ? WEIGHT_BOLD : WEIGHT_NORMAL,
766 [ # # ][ # # ]: 0 : aNewData.mbItalic ? ITALIC_NORMAL : ITALIC_NONE ) );
[ # # ]
767 [ # # ][ # # ]: 0 : aNewData.maStyle = pFontList->GetStyleName( aFontInfo );
[ # # ]
768 [ # # ]: 0 : if( aNewData.maStyle.Len() )
769 [ # # ][ # # ]: 0 : aParaText.Append( ',' ).Append( aNewData.maStyle );
[ # # ]
770 : : }
771 [ # # ]: 0 : aParaText.Append( '"' );
772 : : }
773 : :
774 : : // height
775 : : // is calculated wrong in ScPatternAttr::GetFromEditItemSet, because already in twips and not 100thmm
776 : : // -> get it directly from edit engine item set
777 [ # # ][ # # ]: 0 : aNewData.mnHeight = ulimit_cast< sal_uInt16 >( GETITEM( aEditSet, SvxFontHeightItem, EE_CHAR_FONTHEIGHT ).GetHeight() );
778 : 0 : (aNewData.mnHeight += 10) /= 20;
779 : 0 : bool bFontHtChanged = (aFontData.mnHeight != aNewData.mnHeight);
780 [ # # ]: 0 : if( bFontHtChanged )
781 [ # # ][ # # ]: 0 : aParaText.Append( '&' ).Append( String::CreateFromInt32( aNewData.mnHeight ) );
[ # # ][ # # ]
782 : : // update maximum paragraph height, convert to twips
783 [ # # ]: 0 : nParaHeight = ::std::max< sal_Int32 >( nParaHeight, aNewData.mnHeight * 20 );
784 : :
785 : : // underline
786 : 0 : aNewData.mnUnderline = EXC_FONTUNDERL_NONE;
787 [ # # ]: 0 : switch( aFont.GetUnderline() )
[ # # # # ]
788 : : {
789 : 0 : case UNDERLINE_NONE: aNewData.mnUnderline = EXC_FONTUNDERL_NONE; break;
790 : 0 : case UNDERLINE_SINGLE: aNewData.mnUnderline = EXC_FONTUNDERL_SINGLE; break;
791 : 0 : case UNDERLINE_DOUBLE: aNewData.mnUnderline = EXC_FONTUNDERL_DOUBLE; break;
792 : 0 : default: aNewData.mnUnderline = EXC_FONTUNDERL_SINGLE;
793 : : }
794 [ # # ]: 0 : if( aFontData.mnUnderline != aNewData.mnUnderline )
795 : : {
796 : : sal_uInt8 nTmpUnderl = (aNewData.mnUnderline == EXC_FONTUNDERL_NONE) ?
797 [ # # ]: 0 : aFontData.mnUnderline : aNewData.mnUnderline;
798 [ # # ][ # # ]: 0 : aParaText.AppendAscii( (nTmpUnderl == EXC_FONTUNDERL_SINGLE) ? "&U" : "&E" );
799 : : }
800 : :
801 : : // strikeout
802 [ # # ]: 0 : aNewData.mbStrikeout = (aFont.GetStrikeout() != STRIKEOUT_NONE);
803 [ # # ]: 0 : if( aFontData.mbStrikeout != aNewData.mbStrikeout )
804 [ # # ]: 0 : aParaText.AppendAscii( "&S" );
805 : :
806 : : // super/sub script
807 [ # # ]: 0 : const SvxEscapementItem& rEscapeItem = GETITEM( aEditSet, SvxEscapementItem, EE_CHAR_ESCAPEMENT );
808 [ # # ]: 0 : aNewData.SetScEscapement( rEscapeItem.GetEsc() );
809 [ # # ]: 0 : if( aFontData.mnEscapem != aNewData.mnEscapem )
810 : : {
811 [ # # # # ]: 0 : switch(aNewData.mnEscapem)
812 : : {
813 : : // close the previous super/sub script.
814 [ # # ][ # # ]: 0 : case EXC_FONTESC_NONE: aParaText.AppendAscii( (aFontData.mnEscapem == EXC_FONTESC_SUPER) ? "&X" : "&Y" ); break;
815 [ # # ]: 0 : case EXC_FONTESC_SUPER: aParaText.AppendAscii( "&X" ); break;
816 [ # # ]: 0 : case EXC_FONTESC_SUB: aParaText.AppendAscii( "&Y" ); break;
817 : 0 : default: break;
818 : : }
819 : : }
820 : :
821 [ # # ]: 0 : aFontData = aNewData;
822 : :
823 : : // --- text content or text fields ---
824 : :
825 : : const SfxPoolItem* pItem;
826 [ # # ][ # # ]: 0 : if( (aSel.nStartPos + 1 == aSel.nEndPos) && // fields are single characters
[ # # ]
827 [ # # ]: 0 : (aEditSet.GetItemState( EE_FEATURE_FIELD, false, &pItem ) == SFX_ITEM_SET) )
828 : : {
829 [ # # ]: 0 : if( const SvxFieldData* pFieldData = static_cast< const SvxFieldItem* >( pItem )->GetField() )
830 : : {
831 [ # # ][ # # ]: 0 : if( pFieldData->ISA( SvxPageField ) )
[ # # ]
832 [ # # ]: 0 : aParaText.AppendAscii( "&P" );
833 [ # # ][ # # ]: 0 : else if( pFieldData->ISA( SvxPagesField ) )
[ # # ]
834 [ # # ]: 0 : aParaText.AppendAscii( "&N" );
835 [ # # ][ # # ]: 0 : else if( pFieldData->ISA( SvxDateField ) )
[ # # ]
836 [ # # ]: 0 : aParaText.AppendAscii( "&D" );
837 [ # # ][ # # ]: 0 : else if( pFieldData->ISA( SvxTimeField ) || pFieldData->ISA( SvxExtTimeField ) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
838 [ # # ]: 0 : aParaText.AppendAscii( "&T" );
839 [ # # ][ # # ]: 0 : else if( pFieldData->ISA( SvxTableField ) )
[ # # ]
840 [ # # ]: 0 : aParaText.AppendAscii( "&A" );
841 [ # # ][ # # ]: 0 : else if( pFieldData->ISA( SvxFileField ) ) // title -> file name
[ # # ]
842 [ # # ]: 0 : aParaText.AppendAscii( "&F" );
843 [ # # ][ # # ]: 0 : else if( const SvxExtFileField* pFileField = PTR_CAST( SvxExtFileField, pFieldData ) )
[ # # ][ # # ]
[ # # ]
844 : : {
845 [ # # # # ]: 0 : switch( pFileField->GetFormat() )
846 : : {
847 : : case SVXFILEFORMAT_NAME_EXT:
848 : : case SVXFILEFORMAT_NAME:
849 [ # # ]: 0 : aParaText.AppendAscii( "&F" );
850 : 0 : break;
851 : : case SVXFILEFORMAT_PATH:
852 [ # # ]: 0 : aParaText.AppendAscii( "&Z" );
853 : 0 : break;
854 : : case SVXFILEFORMAT_FULLPATH:
855 [ # # ]: 0 : aParaText.AppendAscii( "&Z&F" );
856 : 0 : break;
857 : : default:
858 : : OSL_FAIL( "XclExpHFConverter::AppendPortion - unknown file field" );
859 : : }
860 : : }
861 : : }
862 : : }
863 : : else
864 : : {
865 [ # # ]: 0 : String aPortionText( mrEE.GetText( aSel ) );
866 [ # # ][ # # ]: 0 : aPortionText.SearchAndReplaceAll( rtl::OUString('&'), rtl::OUString("&&") );
[ # # ][ # # ]
[ # # ]
867 : : // #i17440# space between font height and numbers in text
868 [ # # ][ # # ]: 0 : if( bFontHtChanged && aParaText.Len() && aPortionText.Len() )
[ # # ][ # # ]
869 : : {
870 : 0 : sal_Unicode cLast = aParaText.GetChar( aParaText.Len() - 1 );
871 : 0 : sal_Unicode cFirst = aPortionText.GetChar( 0 );
872 [ # # ][ # # ]: 0 : if( ('0' <= cLast) && (cLast <= '9') && ('0' <= cFirst) && (cFirst <= '9') )
[ # # ][ # # ]
873 [ # # ]: 0 : aParaText.Append( ' ' );
874 : : }
875 [ # # ][ # # ]: 0 : aParaText.Append( aPortionText );
876 [ # # ][ # # ]: 0 : }
877 : : }
878 : :
879 : 0 : aSel.nStartPos = aSel.nEndPos;
880 : : }
881 : :
882 [ # # ]: 0 : ScGlobal::AddToken( aText, aParaText, '\n' );
883 [ # # ]: 0 : if( nParaHeight == 0 )
884 : 0 : nParaHeight = aFontData.mnHeight * 20; // points -> twips
885 : 0 : nHeight += nParaHeight;
886 [ # # ]: 0 : }
887 : :
888 [ # # ]: 0 : mrEE.SetUpdateMode( bOldUpdateMode );
889 : :
890 [ # # ]: 0 : if( aText.Len() )
891 : : {
892 [ # # ][ # # ]: 0 : maHFString.Append( '&' ).Append( cPortionCode ).Append( aText );
[ # # ]
893 [ # # ]: 0 : mnTotalHeight = ::std::max( mnTotalHeight, nHeight );
894 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
895 : : }
896 : :
897 : : // URL conversion =============================================================
898 : :
899 : : namespace {
900 : :
901 : : /** Encodes special parts of the URL, i.e. directory separators and volume names.
902 : : @param pTableName Pointer to a table name to be encoded in this URL, or 0. */
903 : 0 : rtl::OUString lclEncodeDosUrl(
904 : : XclBiff eBiff, const rtl::OUString& rUrl, const rtl::OUString& rBase, const rtl::OUString* pTableName)
905 : : {
906 : 0 : rtl::OUStringBuffer aBuf;
907 : :
908 [ # # ]: 0 : if (!rUrl.isEmpty())
909 : : {
910 : 0 : rtl::OUString aOldUrl = rUrl;
911 [ # # ]: 0 : aBuf.append(EXC_URLSTART_ENCODED);
912 : :
913 [ # # ][ # # ]: 0 : if ( aOldUrl.getLength() > 2 && aOldUrl.copy(0,2) == "\\\\" )
[ # # ][ # # ]
914 : : {
915 : : // UNC
916 [ # # ][ # # ]: 0 : aBuf.append(EXC_URL_DOSDRIVE).append(sal_Unicode('@'));
917 : 0 : aOldUrl = aOldUrl.copy(2);
918 : : }
919 [ # # ][ # # ]: 0 : else if ( aOldUrl.getLength() > 2 && aOldUrl.copy(1,2) == ":\\" )
[ # # ][ # # ]
920 : : {
921 : : // drive letter
922 [ # # ]: 0 : sal_Unicode cThisDrive = rBase.isEmpty() ? ' ' : rBase.getStr()[0];
923 : 0 : sal_Unicode cDrive = aOldUrl.getStr()[0];
924 [ # # ]: 0 : if (cThisDrive == cDrive)
925 : : // This document and the referenced document are under the same drive.
926 [ # # ]: 0 : aBuf.append(EXC_URL_DRIVEROOT);
927 : : else
928 [ # # ][ # # ]: 0 : aBuf.append(EXC_URL_DOSDRIVE).append(cDrive);
929 : 0 : aOldUrl = aOldUrl.copy(3);
930 : : }
931 : :
932 : : // directories
933 : 0 : sal_Int32 nPos = -1;
934 [ # # ]: 0 : while((nPos = aOldUrl.indexOf('\\')) != -1)
935 : : {
936 [ # # ]: 0 : if ( aOldUrl.copy(0,2) == ".." )
937 : : // parent dir (NOTE: the MS-XLS spec doesn't mention this, and
938 : : // Excel seems confused by this token).
939 [ # # ]: 0 : aBuf.append(EXC_URL_PARENTDIR);
940 : : else
941 [ # # ][ # # ]: 0 : aBuf.append(aOldUrl.copy(0,nPos)).append(EXC_URL_SUBDIR);
942 : :
943 : 0 : aOldUrl = aOldUrl.copy(nPos + 1);
944 : : }
945 : :
946 : : // file name
947 [ # # ]: 0 : if (pTableName) // enclose file name in brackets if table name follows
948 [ # # ][ # # ]: 0 : aBuf.append(sal_Unicode('[')).append(aOldUrl).append(sal_Unicode(']'));
[ # # ]
949 : : else
950 [ # # ]: 0 : aBuf.append(aOldUrl);
951 : : }
952 : : else // empty URL -> self reference
953 : : {
954 [ # # # ]: 0 : switch( eBiff )
955 : : {
956 : : case EXC_BIFF5:
957 [ # # ][ # # ]: 0 : aBuf.append(pTableName ? EXC_URLSTART_SELFENCODED : EXC_URLSTART_SELF);
958 : 0 : break;
959 : : case EXC_BIFF8:
960 : : DBG_ASSERT( pTableName, "lclEncodeDosUrl - sheet name required for BIFF8" );
961 [ # # ]: 0 : aBuf.append(EXC_URLSTART_SELF);
962 : 0 : break;
963 : : default:
964 : : DBG_ERROR_BIFF();
965 : : }
966 : : }
967 : :
968 : : // table name
969 [ # # ]: 0 : if (pTableName)
970 [ # # ]: 0 : aBuf.append(*pTableName);
971 : :
972 [ # # ]: 0 : return aBuf.makeStringAndClear();
973 : : }
974 : :
975 : : } // namespace
976 : :
977 : : // ----------------------------------------------------------------------------
978 : :
979 : 0 : rtl::OUString XclExpUrlHelper::EncodeUrl( const XclExpRoot& rRoot, const rtl::OUString& rAbsUrl, const rtl::OUString* pTableName )
980 : : {
981 [ # # ][ # # ]: 0 : rtl::OUString aDosUrl = INetURLObject(rAbsUrl).getFSysPath(INetURLObject::FSYS_DOS);
[ # # ]
982 [ # # ][ # # ]: 0 : rtl::OUString aDosBase = INetURLObject(rRoot.GetBasePath()).getFSysPath(INetURLObject::FSYS_DOS);
[ # # ][ # # ]
983 [ # # ]: 0 : return lclEncodeDosUrl(rRoot.GetBiff(), aDosUrl, aDosBase, pTableName);
984 : : }
985 : :
986 : 0 : rtl::OUString XclExpUrlHelper::EncodeDde( const rtl::OUString& rApplic, const rtl::OUString& rTopic )
987 : : {
988 : 0 : rtl::OUStringBuffer aBuf;
989 [ # # ][ # # ]: 0 : aBuf.append(rApplic).append(EXC_DDE_DELIM).append(rTopic);
[ # # ]
990 [ # # ]: 0 : return aBuf.makeStringAndClear();
991 : : }
992 : :
993 : : // Cached Value Lists =========================================================
994 : :
995 : 0 : XclExpCachedMatrix::XclExpCachedMatrix( const ScMatrix& rMatrix )
996 : 0 : : mrMatrix( rMatrix )
997 : : {
998 : 0 : mrMatrix.IncRef();
999 : 0 : }
1000 : 0 : XclExpCachedMatrix::~XclExpCachedMatrix()
1001 : : {
1002 : 0 : mrMatrix.DecRef();
1003 : 0 : }
1004 : :
1005 : 0 : void XclExpCachedMatrix::GetDimensions( SCSIZE & nCols, SCSIZE & nRows ) const
1006 : : {
1007 : 0 : mrMatrix.GetDimensions( nCols, nRows );
1008 : :
1009 : : OSL_ENSURE( nCols && nRows, "XclExpCachedMatrix::GetDimensions - empty matrix" );
1010 : : OSL_ENSURE( nCols <= 256, "XclExpCachedMatrix::GetDimensions - too many columns" );
1011 : 0 : }
1012 : :
1013 : 0 : sal_Size XclExpCachedMatrix::GetSize() const
1014 : : {
1015 : : SCSIZE nCols, nRows;
1016 : :
1017 [ # # ]: 0 : GetDimensions( nCols, nRows );
1018 : :
1019 : : /* The returned size may be wrong if the matrix contains strings. The only
1020 : : effect is that the export stream has to update a wrong record size which is
1021 : : faster than to iterate through all cached values and calculate their sizes. */
1022 : 0 : return 3 + 9 * (nCols * nRows);
1023 : : }
1024 : :
1025 : 0 : void XclExpCachedMatrix::Save( XclExpStream& rStrm ) const
1026 : : {
1027 : : SCSIZE nCols, nRows;
1028 : :
1029 [ # # ]: 0 : GetDimensions( nCols, nRows );
1030 : :
1031 [ # # ]: 0 : if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 )
1032 : : // in BIFF2-BIFF7: 256 columns represented by 0 columns
1033 [ # # ][ # # ]: 0 : rStrm << static_cast< sal_uInt8 >( nCols ) << static_cast< sal_uInt16 >( nRows );
1034 : : else
1035 : : // in BIFF8: columns and rows decreaed by 1
1036 [ # # ][ # # ]: 0 : rStrm << static_cast< sal_uInt8 >( nCols - 1 ) << static_cast< sal_uInt16 >( nRows - 1 );
1037 : :
1038 [ # # ]: 0 : for( SCSIZE nRow = 0; nRow < nRows; ++nRow )
1039 : : {
1040 [ # # ]: 0 : for( SCSIZE nCol = 0; nCol < nCols; ++nCol )
1041 : : {
1042 [ # # ]: 0 : ScMatrixValue nMatVal = mrMatrix.Get( nCol, nRow );
1043 : :
1044 [ # # ]: 0 : if( SC_MATVAL_EMPTY == nMatVal.nType )
1045 : : {
1046 [ # # ]: 0 : rStrm.SetSliceSize( 9 );
1047 [ # # ]: 0 : rStrm << EXC_CACHEDVAL_EMPTY;
1048 [ # # ]: 0 : rStrm.WriteZeroBytes( 8 );
1049 : : }
1050 [ # # ]: 0 : else if( ScMatrix::IsNonValueType( nMatVal.nType ) )
1051 : : {
1052 [ # # ]: 0 : XclExpString aStr( nMatVal.GetString(), EXC_STR_DEFAULT );
1053 [ # # ]: 0 : rStrm.SetSliceSize( 6 );
1054 [ # # ][ # # ]: 0 : rStrm << EXC_CACHEDVAL_STRING << aStr;
1055 : : }
1056 [ # # ]: 0 : else if( SC_MATVAL_BOOLEAN == nMatVal.nType )
1057 : : {
1058 : 0 : sal_Int8 nBool = nMatVal.GetBoolean();
1059 [ # # ]: 0 : rStrm.SetSliceSize( 9 );
1060 [ # # ][ # # ]: 0 : rStrm << EXC_CACHEDVAL_BOOL << nBool;
1061 [ # # ]: 0 : rStrm.WriteZeroBytes( 7 );
1062 : : }
1063 [ # # ]: 0 : else if( sal_uInt16 nScError = nMatVal.GetError() )
1064 : : {
1065 [ # # ]: 0 : sal_Int8 nError ( XclTools::GetXclErrorCode( nScError ) );
1066 [ # # ]: 0 : rStrm.SetSliceSize( 9 );
1067 [ # # ][ # # ]: 0 : rStrm << EXC_CACHEDVAL_ERROR << nError;
1068 [ # # ]: 0 : rStrm.WriteZeroBytes( 7 );
1069 : : }
1070 : : else
1071 : : {
1072 [ # # ]: 0 : rStrm.SetSliceSize( 9 );
1073 [ # # ][ # # ]: 0 : rStrm << EXC_CACHEDVAL_DOUBLE << nMatVal.fVal;
1074 : : }
1075 : 0 : }
1076 : : }
1077 [ + - ][ + - ]: 24 : }
1078 : :
1079 : : // ============================================================================
1080 : :
1081 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|