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 .
21 #include <xistring.hxx>
22 #include <xlstyle.hxx>
23 #include <xistream.hxx>
25 #include <xltools.hxx>
26 #include <sal/log.hxx>
28 // Byte/Unicode strings =======================================================
30 /** All allowed flags for import. */
31 const XclStrFlags nAllowedFlags
= XclStrFlags::EightBitLength
| XclStrFlags::SmartFlags
| XclStrFlags::SeparateFormats
;
33 XclImpString::XclImpString()
37 XclImpString::XclImpString( OUString aString
) :
38 maString(std::move( aString
))
42 void XclImpString::Read( XclImpStream
& rStrm
, XclStrFlags nFlags
)
44 if( !( nFlags
& XclStrFlags::SeparateFormats
) )
48 nFlags
& ~nAllowedFlags
, "sc.filter",
49 "XclImpString::Read - unknown flag");
50 bool b16BitLen
= !( nFlags
& XclStrFlags::EightBitLength
);
52 switch( rStrm
.GetRoot().GetBiff() )
58 // no integrated formatting in BIFF2-BIFF7
59 maString
= rStrm
.ReadByteString( b16BitLen
);
64 // --- string header ---
65 sal_uInt16 nChars
= b16BitLen
? rStrm
.ReaduInt16() : rStrm
.ReaduInt8();
66 sal_uInt8 nFlagField
= 0;
67 if( nChars
|| !( nFlags
& XclStrFlags::SmartFlags
) )
68 nFlagField
= rStrm
.ReaduInt8();
70 bool b16Bit
, bRich
, bFarEast
;
73 rStrm
.ReadUniStringExtHeader( b16Bit
, bRich
, bFarEast
, nRunCount
, nExtInf
, nFlagField
);
74 // ignore the flags, they may be wrong
76 // --- character array ---
77 maString
= rStrm
.ReadRawUniString( nChars
, b16Bit
);
81 ReadFormats( rStrm
, maFormats
, nRunCount
);
83 // --- extended (FarEast) information ---
84 rStrm
.Ignore( nExtInf
);
93 void XclImpString::AppendFormat( XclFormatRunVec
& rFormats
, sal_uInt16 nChar
, sal_uInt16 nFontIdx
)
95 // #i33341# real life -- same character index may occur several times
96 OSL_ENSURE( rFormats
.empty() || (rFormats
.back().mnChar
<= nChar
), "XclImpString::AppendFormat - wrong char order" );
97 if( rFormats
.empty() || (rFormats
.back().mnChar
< nChar
) )
98 rFormats
.emplace_back( nChar
, nFontIdx
);
100 rFormats
.back().mnFontIdx
= nFontIdx
;
103 void XclImpString::ReadFormats( XclImpStream
& rStrm
, XclFormatRunVec
& rFormats
)
105 bool bBiff8
= rStrm
.GetRoot().GetBiff() == EXC_BIFF8
;
106 sal_uInt16 nRunCount
= bBiff8
? rStrm
.ReaduInt16() : rStrm
.ReaduInt8();
107 ReadFormats( rStrm
, rFormats
, nRunCount
);
110 void XclImpString::ReadFormats( XclImpStream
& rStrm
, XclFormatRunVec
& rFormats
, sal_uInt16 nRunCount
)
114 size_t nElementSize
= rStrm
.GetRoot().GetBiff() == EXC_BIFF8
? 4 : 2;
115 size_t nAvailableBytes
= rStrm
.GetRecLeft();
116 size_t nMaxElements
= nAvailableBytes
/ nElementSize
;
117 if (nRunCount
> nMaxElements
)
119 SAL_WARN("sc.filter", "XclImpString::ReadFormats - more formats claimed than stream could contain");
120 rStrm
.SetSvStreamError(SVSTREAM_FILEFORMAT_ERROR
);
124 rFormats
.reserve( nRunCount
);
125 /* #i33341# real life -- same character index may occur several times
126 -> use AppendFormat() to validate formats */
127 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
129 for( sal_uInt16 nIdx
= 0; nIdx
< nRunCount
; ++nIdx
)
131 sal_uInt16 nChar
= rStrm
.ReaduInt16();
132 sal_uInt16 nFontIdx
= rStrm
.ReaduInt16();
133 AppendFormat( rFormats
, nChar
, nFontIdx
);
138 for( sal_uInt16 nIdx
= 0; nIdx
< nRunCount
; ++nIdx
)
140 sal_uInt8 nChar
= rStrm
.ReaduInt8();
141 sal_uInt8 nFontIdx
= rStrm
.ReaduInt8();
142 AppendFormat( rFormats
, nChar
, nFontIdx
);
147 void XclImpString::ReadObjFormats( XclImpStream
& rStrm
, XclFormatRunVec
& rFormats
, sal_uInt16 nFormatSize
)
149 // number of formatting runs, each takes 8 bytes
150 sal_uInt16 nRunCount
= nFormatSize
/ 8;
152 rFormats
.reserve( nRunCount
);
153 for( sal_uInt16 nIdx
= 0; nIdx
< nRunCount
; ++nIdx
)
155 sal_uInt16 nChar
= rStrm
.ReaduInt16();
156 sal_uInt16 nFontIdx
= rStrm
.ReaduInt16();
158 AppendFormat( rFormats
, nChar
, nFontIdx
);
162 // String iterator ============================================================
164 XclImpStringIterator::XclImpStringIterator( const XclImpString
& rString
) :
165 mrText( rString
.GetText() ),
166 mrFormats( rString
.GetFormats() ),
173 // first portion is formatted, adjust vector index to next portion
174 if( !mrFormats
.empty() && (mrFormats
.front().mnChar
== 0) )
176 // find end position of the first portion
177 mnTextEnd
= (mnFormatsEnd
< mrFormats
.size() ?
178 mrFormats
[ mnFormatsEnd
].mnChar
: mrText
.getLength() );
181 OUString
XclImpStringIterator::GetPortionText() const
183 return mrText
.copy( mnTextBeg
, mnTextEnd
- mnTextBeg
);
186 sal_uInt16
XclImpStringIterator::GetPortionFont() const
188 return (mnFormatsBeg
< mnFormatsEnd
) ? mrFormats
[ mnFormatsBeg
].mnFontIdx
: EXC_FONT_NOTFOUND
;
191 XclImpStringIterator
& XclImpStringIterator::operator++()
198 // indexes into vector of formatting runs
199 if( mnFormatsBeg
< mnFormatsEnd
)
201 if( mnFormatsEnd
< mrFormats
.size() )
203 // character positions of next portion
204 mnTextBeg
= mnTextEnd
;
205 mnTextEnd
= (mnFormatsEnd
< mrFormats
.size()) ?
206 mrFormats
[ mnFormatsEnd
].mnChar
: mrText
.getLength();
208 while( Is() && (mnTextBeg
== mnTextEnd
) );
213 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */