xref: /trunk/main/sc/source/filter/excel/xistring.cxx (revision b77af630)
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_scfilt.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