1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "precompiled_sc.hxx"
25 #include "xistring.hxx"
26 #include "xlstyle.hxx"
27 #include "xistream.hxx"
28 #include "xiroot.hxx"
29
30 // Byte/Unicode strings =======================================================
31
32 /** All allowed flags for import. */
33 const XclStrFlags nAllowedFlags = EXC_STR_8BITLENGTH | EXC_STR_SMARTFLAGS | EXC_STR_SEPARATEFORMATS;
34
35 // ----------------------------------------------------------------------------
36
XclImpString()37 XclImpString::XclImpString()
38 {
39 }
40
XclImpString(const String & rString)41 XclImpString::XclImpString( const String& rString ) :
42 maString( rString )
43 {
44 }
45
~XclImpString()46 XclImpString::~XclImpString()
47 {
48 }
49
Read(XclImpStream & rStrm,XclStrFlags nFlags)50 void XclImpString::Read( XclImpStream& rStrm, XclStrFlags nFlags )
51 {
52 if( !::get_flag( nFlags, EXC_STR_SEPARATEFORMATS ) )
53 maFormats.clear();
54
55 DBG_ASSERT( (nFlags & ~nAllowedFlags) == 0, "XclImpString::Read - unknown flag" );
56 bool b16BitLen = !::get_flag( nFlags, EXC_STR_8BITLENGTH );
57
58 switch( rStrm.GetRoot().GetBiff() )
59 {
60 case EXC_BIFF2:
61 case EXC_BIFF3:
62 case EXC_BIFF4:
63 case EXC_BIFF5:
64 // no integrated formatting in BIFF2-BIFF7
65 maString = rStrm.ReadByteString( b16BitLen );
66 break;
67
68 case EXC_BIFF8:
69 {
70 // --- string header ---
71 sal_uInt16 nChars = b16BitLen ? rStrm.ReaduInt16() : rStrm.ReaduInt8();
72 sal_uInt8 nFlagField = 0;
73 if( nChars || !::get_flag( nFlags, EXC_STR_SMARTFLAGS ) )
74 rStrm >> nFlagField;
75
76 bool b16Bit, bRich, bFarEast;
77 sal_uInt16 nRunCount;
78 sal_uInt32 nExtInf;
79 rStrm.ReadUniStringExtHeader( b16Bit, bRich, bFarEast, nRunCount, nExtInf, nFlagField );
80 // #122185# ignore the flags, they may be wrong
81
82 // --- character array ---
83 maString = rStrm.ReadRawUniString( nChars, b16Bit );
84
85 // --- formatting ---
86 if( nRunCount > 0 )
87 ReadFormats( rStrm, nRunCount );
88
89 // --- extended (FarEast) information ---
90 rStrm.Ignore( nExtInf );
91 }
92 break;
93
94 default:
95 DBG_ERROR_BIFF();
96 }
97 }
98
AppendFormat(XclFormatRunVec & rFormats,sal_uInt16 nChar,sal_uInt16 nFontIdx)99 void XclImpString::AppendFormat( XclFormatRunVec& rFormats, sal_uInt16 nChar, sal_uInt16 nFontIdx )
100 {
101 // #i33341# real life -- same character index may occur several times
102 DBG_ASSERT( rFormats.empty() || (rFormats.back().mnChar <= nChar), "XclImpString::AppendFormat - wrong char order" );
103 if( rFormats.empty() || (rFormats.back().mnChar < nChar) )
104 rFormats.push_back( XclFormatRun( nChar, nFontIdx ) );
105 else
106 rFormats.back().mnFontIdx = nFontIdx;
107 }
108
ReadFormats(XclImpStream & rStrm,XclFormatRunVec & rFormats)109 void XclImpString::ReadFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats )
110 {
111 bool bBiff8 = rStrm.GetRoot().GetBiff() == EXC_BIFF8;
112 sal_uInt16 nRunCount = bBiff8 ? rStrm.ReaduInt16() : rStrm.ReaduInt8();
113 ReadFormats( rStrm, rFormats, nRunCount );
114 }
115
ReadFormats(XclImpStream & rStrm,XclFormatRunVec & rFormats,sal_uInt16 nRunCount)116 void XclImpString::ReadFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats, sal_uInt16 nRunCount )
117 {
118 rFormats.clear();
119 rFormats.reserve( nRunCount );
120 /* #i33341# real life -- same character index may occur several times
121 -> use AppendFormat() to validate formats */
122 if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
123 {
124 for( sal_uInt16 nIdx = 0; nIdx < nRunCount; ++nIdx )
125 {
126 sal_uInt16 nChar, nFontIdx;
127 rStrm >> nChar >> nFontIdx;
128 AppendFormat( rFormats, nChar, nFontIdx );
129 }
130 }
131 else
132 {
133 for( sal_uInt16 nIdx = 0; nIdx < nRunCount; ++nIdx )
134 {
135 sal_uInt8 nChar, nFontIdx;
136 rStrm >> nChar >> nFontIdx;
137 AppendFormat( rFormats, nChar, nFontIdx );
138 }
139 }
140 }
141
ReadObjFormats(XclImpStream & rStrm,XclFormatRunVec & rFormats,sal_uInt16 nFormatSize)142 void XclImpString::ReadObjFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats, sal_uInt16 nFormatSize )
143 {
144 // number of formatting runs, each takes 8 bytes
145 sal_uInt16 nRunCount = nFormatSize / 8;
146 rFormats.clear();
147 rFormats.reserve( nRunCount );
148 for( sal_uInt16 nIdx = 0; nIdx < nRunCount; ++nIdx )
149 {
150 sal_uInt16 nChar, nFontIdx;
151 rStrm >> nChar >> nFontIdx;
152 rStrm.Ignore( 4 );
153 AppendFormat( rFormats, nChar, nFontIdx );
154 }
155 }
156
157 // String iterator ============================================================
158
XclImpStringIterator(const XclImpString & rString)159 XclImpStringIterator::XclImpStringIterator( const XclImpString& rString ) :
160 mrText( rString.GetText() ),
161 mrFormats( rString.GetFormats() ),
162 mnPortion( 0 ),
163 mnTextBeg( 0 ),
164 mnTextEnd( 0 ),
165 mnFormatsBeg( 0 ),
166 mnFormatsEnd( 0 )
167 {
168 // first portion is formatted, adjust vector index to next portion
169 if( !mrFormats.empty() && (mrFormats.front().mnChar == 0) )
170 ++mnFormatsEnd;
171 // find end position of the first portion
172 mnTextEnd = static_cast< xub_StrLen >( (mnFormatsEnd < mrFormats.size()) ?
173 mrFormats[ mnFormatsEnd ].mnChar : mrText.Len() );
174 }
175
GetPortionText() const176 String XclImpStringIterator::GetPortionText() const
177 {
178 return String( mrText, mnTextBeg, mnTextEnd - mnTextBeg );
179 }
180
GetPortionFont() const181 sal_uInt16 XclImpStringIterator::GetPortionFont() const
182 {
183 return (mnFormatsBeg < mnFormatsEnd) ? mrFormats[ mnFormatsBeg ].mnFontIdx : EXC_FONT_NOTFOUND;
184 }
185
operator ++()186 XclImpStringIterator& XclImpStringIterator::operator++()
187 {
188 if( Is() )
189 {
190 ++mnPortion;
191 do
192 {
193 // indexes into vector of formatting runs
194 if( mnFormatsBeg < mnFormatsEnd )
195 ++mnFormatsBeg;
196 if( mnFormatsEnd < mrFormats.size() )
197 ++mnFormatsEnd;
198 // character positions of next portion
199 mnTextBeg = mnTextEnd;
200 mnTextEnd = static_cast< xub_StrLen >( (mnFormatsEnd < mrFormats.size()) ?
201 mrFormats[ mnFormatsEnd ].mnChar : mrText.Len() );
202 }
203 while( Is() && (mnTextBeg == mnTextEnd) );
204 }
205 return *this;
206 }
207
208 // ============================================================================
209
210