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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 #include "lotimpop.hxx" 27 #include <vos/mutex.hxx> 28 29 #include "attrib.hxx" 30 #include "document.hxx" 31 #include "rangenam.hxx" 32 #include "cell.hxx" 33 #include "patattr.hxx" 34 #include "docpool.hxx" 35 #include "compiler.hxx" 36 #include "global.hxx" 37 38 #include "root.hxx" 39 #include "lotfntbf.hxx" 40 #include "lotform.hxx" 41 #include "tool.h" 42 #include "namebuff.hxx" 43 #include "lotrange.hxx" 44 #include "lotattr.hxx" 45 46 47 static vos:: OMutex aLotImpSemaphore; 48 49 50 ImportLotus::ImportLotus( SvStream& aStream, ScDocument* pDoc, CharSet eQ ) : 51 ImportTyp( pDoc, eQ ), 52 pIn( &aStream ), 53 aConv( *pIn, eQ, sal_False ) 54 { 55 // good point to start locking of import lotus 56 aLotImpSemaphore.acquire(); 57 58 pLotusRoot = new LOTUS_ROOT; 59 pLotusRoot->pDoc = pDoc; 60 pLotusRoot->pRangeNames = new LotusRangeList; 61 pLotusRoot->pScRangeName = pDoc->GetRangeName(); 62 pLotusRoot->eCharsetQ = eQ; 63 pLotusRoot->eFirstType = Lotus_X; 64 pLotusRoot->eActType = Lotus_X; 65 pLotusRoot->pRngNmBffWK3 = new RangeNameBufferWK3; 66 pFontBuff = pLotusRoot->pFontBuff = new LotusFontBuffer; 67 pLotusRoot->pAttrTable = new LotAttrTable; 68 } 69 70 71 ImportLotus::~ImportLotus() 72 { 73 delete pLotusRoot->pRangeNames; 74 delete pLotusRoot->pRngNmBffWK3; 75 delete pFontBuff; 76 delete pLotusRoot->pAttrTable; 77 delete pLotusRoot; 78 79 #ifdef DBG_UTIL 80 pLotusRoot = NULL; 81 #endif 82 83 // no need 4 pLotusRoot anymore 84 aLotImpSemaphore.release(); 85 } 86 87 88 void ImportLotus::Bof( void ) 89 { 90 sal_uInt16 nFileCode, nFileSub, nSaveCnt; 91 sal_uInt8 nMajorId, nMinorId, nFlags; 92 93 Read( nFileCode ); 94 Read( nFileSub ); 95 Read( pLotusRoot->aActRange ); 96 Read( nSaveCnt ); 97 Read( nMajorId ); 98 Read( nMinorId ); 99 Skip( 1 ); 100 Read( nFlags ); 101 102 if( nFileSub == 0x0004 ) 103 { 104 if( nFileCode == 0x1000 ) 105 {// <= WK3 106 pLotusRoot->eFirstType = pLotusRoot->eActType = Lotus_WK3; 107 } 108 else if( nFileCode == 0x1002 ) 109 {// WK4 110 pLotusRoot->eFirstType = pLotusRoot->eActType = Lotus_WK4; 111 } 112 } 113 } 114 115 116 sal_Bool ImportLotus::BofFm3( void ) 117 { 118 sal_uInt16 nFileCode, nFileSub; 119 120 Read( nFileCode ); 121 Read( nFileSub ); 122 123 return ( nFileCode == 0x8007 && ( nFileSub == 0x0000 || nFileSub == 0x00001 ) ); 124 } 125 126 127 void ImportLotus::Columnwidth( sal_uInt16 nRecLen ) 128 { 129 DBG_ASSERT( nRecLen >= 4, "*ImportLotus::Columnwidth(): Record zu kurz!" ); 130 131 sal_uInt8 nLTab, nWindow2; 132 sal_uInt16 nCnt = ( nRecLen - 4 ) / 2; 133 134 Read( nLTab ); 135 Read( nWindow2 ); 136 137 if( !pD->HasTable( static_cast<SCTAB> (nLTab) ) ) 138 pD->MakeTable( static_cast<SCTAB> (nLTab) ); 139 140 if( !nWindow2 ) 141 { 142 Skip( 2 ); 143 144 sal_uInt8 nCol, nSpaces; 145 146 while( nCnt ) 147 { 148 Read( nCol ); 149 Read( nSpaces ); 150 // ACHTUNG: Korrekturfaktor nach 'Augenmass' ermittelt! 151 pD->SetColWidth( static_cast<SCCOL> (nCol), static_cast<SCTAB> (nLTab), ( sal_uInt16 ) ( TWIPS_PER_CHAR * 1.28 * nSpaces ) ); 152 153 nCnt--; 154 } 155 } 156 } 157 158 159 void ImportLotus::Hiddencolumn( sal_uInt16 nRecLen ) 160 { 161 DBG_ASSERT( nRecLen >= 4, "*ImportLotus::Hiddencolumn(): Record zu kurz!" ); 162 163 sal_uInt8 nLTab, nWindow2; 164 sal_uInt16 nCnt = ( nRecLen - 4 ) / 2; 165 166 Read( nLTab ); 167 Read( nWindow2 ); 168 169 if( !nWindow2 ) 170 { 171 Skip( 2 ); 172 173 sal_uInt8 nCol; 174 175 while( nCnt ) 176 { 177 Read( nCol ); 178 179 pD->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), static_cast<SCTAB>(nLTab), true); 180 nCnt--; 181 } 182 } 183 } 184 185 186 void ImportLotus::Userrange( void ) 187 { 188 sal_uInt16 nRangeType; 189 ScRange aScRange; 190 sal_Char* pBuffer = new sal_Char[ 32 ]; 191 192 Read( nRangeType ); 193 194 pIn->Read( pBuffer, 16 ); 195 pBuffer[ 16 ] = ( sal_Char ) 0x00; // zur Sicherheit... 196 String aName( pBuffer, eQuellChar ); 197 198 Read( aScRange ); 199 200 pLotusRoot->pRngNmBffWK3->Add( aName, aScRange ); 201 delete[] pBuffer; 202 } 203 204 205 void ImportLotus::Errcell( void ) 206 { 207 ScAddress aA; 208 209 Read( aA ); 210 211 pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( CREATE_STRING( "#ERR!" ) ), (sal_Bool)sal_True ); 212 } 213 214 215 void ImportLotus::Nacell( void ) 216 { 217 ScAddress aA; 218 219 Read( aA ); 220 221 pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( CREATE_STRING( "#NA!" ) ), (sal_Bool)sal_True ); 222 } 223 224 225 void ImportLotus::Labelcell( void ) 226 { 227 ScAddress aA; 228 String aLabel; 229 sal_Char cAlign; 230 231 Read( aA ); 232 Read( cAlign ); 233 Read( aLabel ); 234 235 // aLabel.Convert( pLotusRoot->eCharsetQ ); 236 237 pD->PutCell( aA.Col(), aA.Row(), aA.Tab(), new ScStringCell( aLabel ), (sal_Bool)sal_True ); 238 } 239 240 241 void ImportLotus::Numbercell( void ) 242 { 243 ScAddress aAddr; 244 double fVal; 245 246 Read( aAddr ); 247 Read( fVal ); 248 249 pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(), 250 new ScValueCell( fVal ), (sal_Bool)sal_True ); 251 } 252 253 254 void ImportLotus::Smallnumcell( void ) 255 { 256 ScAddress aAddr; 257 sal_Int16 nVal; 258 259 Read( aAddr ); 260 Read( nVal ); 261 262 pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(), 263 new ScValueCell( SnumToDouble( nVal ) ), ( sal_Bool ) sal_True ); 264 } 265 266 267 ScFormulaCell *ImportLotus::Formulacell( sal_uInt16 n ) 268 { 269 DBG_ASSERT( pIn, "-ImportLotus::Formulacell(): Null-Stream -> Rums!" ); 270 271 ScAddress aAddr; 272 273 Read( aAddr ); 274 Skip( 10 ); 275 276 n -= 14; 277 278 const ScTokenArray* pErg; 279 sal_Int32 nRest = n; 280 281 aConv.Reset( aAddr ); 282 aConv.SetWK3(); 283 aConv.Convert( pErg, nRest ); 284 285 ScFormulaCell* pZelle = new ScFormulaCell( pD, aAddr, pErg ); 286 287 pZelle->AddRecalcMode( RECALCMODE_ONLOAD_ONCE ); 288 289 pD->PutCell( aAddr.Col(), aAddr.Row(), aAddr.Tab(), pZelle, (sal_Bool)sal_True ); 290 291 return NULL; 292 } 293 294 295 void ImportLotus::Read( String &r ) 296 { 297 ScfTools::AppendCString( *pIn, r, eQuellChar ); 298 } 299 300 301 void ImportLotus::RowPresentation( sal_uInt16 nRecLen ) 302 { 303 DBG_ASSERT( nRecLen > 4, "*ImportLotus::RowPresentation(): Record zu kurz!" ); 304 305 sal_uInt8 nLTab, nFlags; 306 sal_uInt16 nRow, nHeight; 307 sal_uInt16 nCnt = ( nRecLen - 4 ) / 8; 308 309 Read( nLTab ); 310 Skip( 1 ); 311 312 while( nCnt ) 313 { 314 Read( nRow ); 315 Read( nHeight ); 316 Skip( 2 ); 317 Read( nFlags ); 318 Skip( 1 ); 319 320 if( nFlags & 0x02 ) // Fixed / Strech to fit fonts 321 { // fixed 322 // Height in Lotus in 1/32 Points 323 nHeight *= 20; // -> 32 * TWIPS 324 nHeight /= 32; // -> TWIPS 325 326 pD->SetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), pD->GetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab) ) | CR_MANUALSIZE ); 327 328 pD->SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), nHeight ); 329 } 330 331 nCnt--; 332 } 333 } 334 335 336 void ImportLotus::NamedSheet( void ) 337 { 338 sal_uInt16 nLTab; 339 String aName; 340 341 Read( nLTab ); 342 Read( aName ); 343 344 if( pD->HasTable( static_cast<SCTAB> (nLTab) ) ) 345 pD->RenameTab( static_cast<SCTAB> (nLTab), aName ); 346 else 347 pD->InsertTab( static_cast<SCTAB> (nLTab), aName ); 348 } 349 350 351 void ImportLotus::Font_Face( void ) 352 { 353 sal_uInt8 nNum; 354 String aName; 355 356 Read( nNum ); 357 358 // ACHTUNG: QUICK-HACK gegen unerklaerliche Loops 359 if( nNum > 7 ) 360 return; 361 // ACHTUNG 362 363 Read( aName ); 364 365 pFontBuff->SetName( nNum, aName ); 366 } 367 368 369 void ImportLotus::Font_Type( void ) 370 { 371 static const sal_uInt16 nAnz = 8; 372 sal_uInt16 nCnt; 373 sal_uInt16 nType; 374 375 for( nCnt = 0 ; nCnt < nAnz ; nCnt++ ) 376 { 377 Read( nType ); 378 pFontBuff->SetType( nCnt, nType ); 379 } 380 } 381 382 383 void ImportLotus::Font_Ysize( void ) 384 { 385 static const sal_uInt16 nAnz = 8; 386 sal_uInt16 nCnt; 387 sal_uInt16 nSize; 388 389 for( nCnt = 0 ; nCnt < nAnz ; nCnt++ ) 390 { 391 Read( nSize ); 392 pFontBuff->SetHeight( nCnt, nSize ); 393 } 394 } 395 396 397 void ImportLotus::_Row( const sal_uInt16 nRecLen ) 398 { 399 DBG_ASSERT( nExtTab >= 0, "*ImportLotus::_Row(): Kann hier nicht sein!" ); 400 401 sal_uInt16 nRow; 402 sal_uInt16 nHeight; 403 sal_uInt16 nCntDwn = ( nRecLen - 4 ) / 5; 404 SCCOL nColCnt = 0; 405 sal_uInt8 nRepeats; 406 LotAttrWK3 aAttr; 407 408 sal_Bool bCenter = sal_False; 409 SCCOL nCenterStart = 0, nCenterEnd = 0; 410 411 Read( nRow ); 412 Read( nHeight ); 413 414 nHeight &= 0x0FFF; 415 nHeight *= 22; 416 417 if( nHeight ) 418 pD->SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nExtTab), nHeight ); 419 420 while( nCntDwn ) 421 { 422 Read( aAttr ); 423 Read( nRepeats ); 424 425 if( aAttr.HasStyles() ) 426 pLotusRoot->pAttrTable->SetAttr( 427 nColCnt, static_cast<SCCOL> ( nColCnt + nRepeats ), static_cast<SCROW> (nRow), aAttr ); 428 429 // hier und NICHT in class LotAttrTable, weil nur Attributiert wird, 430 // wenn die anderen Attribute gesetzt sind 431 // -> bei Center-Attribute wird generell zentriert gesetzt 432 if( aAttr.IsCentered() ) 433 { 434 if( bCenter ) 435 { 436 if( pD->HasData( nColCnt, static_cast<SCROW> (nRow), static_cast<SCTAB> (nExtTab) ) ) 437 {// neue Center nach vorheriger Center 438 pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) ); 439 nCenterStart = nColCnt; 440 } 441 } 442 else 443 {// ganz neue Center 444 bCenter = sal_True; 445 nCenterStart = nColCnt; 446 } 447 nCenterEnd = nColCnt + static_cast<SCCOL>(nRepeats); 448 } 449 else 450 { 451 if( bCenter ) 452 {// evtl. alte Center bemachen 453 pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) ); 454 bCenter = sal_False; 455 } 456 } 457 458 nColCnt = nColCnt + static_cast<SCCOL>(nRepeats); 459 nColCnt++; 460 461 nCntDwn--; 462 } 463 464 if( bCenter ) 465 // evtl. alte Center bemachen 466 pD->DoMerge( static_cast<SCTAB> (nExtTab), nCenterStart, static_cast<SCROW> (nRow), nCenterEnd, static_cast<SCROW> (nRow) ); 467 } 468 469 470