| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| #include "xihelper.hxx" |
| #include <svl/itemset.hxx> |
| #include <editeng/editobj.hxx> |
| #include <tools/urlobj.hxx> |
| #include "scitems.hxx" |
| #include <editeng/eeitem.hxx> |
| #include <editeng/flditem.hxx> |
| #include "document.hxx" |
| #include "cell.hxx" |
| #include "rangelst.hxx" |
| #include "editutil.hxx" |
| #include "attrib.hxx" |
| #include "xltracer.hxx" |
| #include "xistream.hxx" |
| #include "xistyle.hxx" |
| |
| #include "excform.hxx" |
| |
| // Excel->Calc cell address/range conversion ================================== |
| |
| namespace { |
| |
| /** Fills the passed Calc address with the passed Excel cell coordinates without checking any limits. */ |
| inline void lclFillAddress( ScAddress& rScPos, sal_uInt16 nXclCol, sal_uInt16 nXclRow, SCTAB nScTab ) |
| { |
| rScPos.SetCol( static_cast< SCCOL >( nXclCol ) ); |
| rScPos.SetRow( static_cast< SCROW >( nXclRow ) ); |
| rScPos.SetTab( nScTab ); |
| } |
| |
| } // namespace |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclImpAddressConverter::XclImpAddressConverter( const XclImpRoot& rRoot ) : |
| XclAddressConverterBase( rRoot.GetTracer(), rRoot.GetScMaxPos() ) |
| { |
| } |
| |
| // cell address --------------------------------------------------------------- |
| |
| bool XclImpAddressConverter::CheckAddress( const XclAddress& rXclPos, bool bWarn ) |
| { |
| bool bValidCol = rXclPos.mnCol <= mnMaxCol; |
| bool bValidRow = rXclPos.mnRow <= mnMaxRow; |
| bool bValid = bValidCol && bValidRow; |
| if( !bValid && bWarn ) |
| { |
| mbColTrunc |= !bValidCol; |
| mbRowTrunc |= !bValidRow; |
| mrTracer.TraceInvalidAddress( ScAddress( |
| static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), 0 ), maMaxPos ); |
| } |
| return bValid; |
| } |
| |
| bool XclImpAddressConverter::ConvertAddress( ScAddress& rScPos, |
| const XclAddress& rXclPos, SCTAB nScTab, bool bWarn ) |
| { |
| bool bValid = CheckAddress( rXclPos, bWarn ); |
| if( bValid ) |
| lclFillAddress( rScPos, rXclPos.mnCol, rXclPos.mnRow, nScTab ); |
| return bValid; |
| } |
| |
| ScAddress XclImpAddressConverter::CreateValidAddress( |
| const XclAddress& rXclPos, SCTAB nScTab, bool bWarn ) |
| { |
| ScAddress aScPos( ScAddress::UNINITIALIZED ); |
| if( !ConvertAddress( aScPos, rXclPos, nScTab, bWarn ) ) |
| { |
| aScPos.SetCol( static_cast< SCCOL >( ::std::min( rXclPos.mnCol, mnMaxCol ) ) ); |
| aScPos.SetRow( static_cast< SCROW >( ::std::min( rXclPos.mnRow, mnMaxRow ) ) ); |
| aScPos.SetTab( limit_cast< SCTAB >( nScTab, 0, maMaxPos.Tab() ) ); |
| } |
| return aScPos; |
| } |
| |
| // cell range ----------------------------------------------------------------- |
| |
| bool XclImpAddressConverter::CheckRange( const XclRange& rXclRange, bool bWarn ) |
| { |
| return CheckAddress( rXclRange.maFirst, bWarn ) && CheckAddress( rXclRange.maLast, bWarn ); |
| } |
| |
| bool XclImpAddressConverter::ConvertRange( ScRange& rScRange, |
| const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn ) |
| { |
| // check start position |
| bool bValidStart = CheckAddress( rXclRange.maFirst, bWarn ); |
| if( bValidStart ) |
| { |
| lclFillAddress( rScRange.aStart, rXclRange.maFirst.mnCol, rXclRange.maFirst.mnRow, nScTab1 ); |
| |
| // check & correct end position |
| sal_uInt16 nXclCol2 = rXclRange.maLast.mnCol; |
| sal_uInt16 nXclRow2 = rXclRange.maLast.mnRow; |
| if( !CheckAddress( rXclRange.maLast, bWarn ) ) |
| { |
| nXclCol2 = ::std::min( nXclCol2, mnMaxCol ); |
| nXclRow2 = ::std::min( nXclRow2, mnMaxRow ); |
| } |
| lclFillAddress( rScRange.aEnd, nXclCol2, nXclRow2, nScTab2 ); |
| } |
| return bValidStart; |
| } |
| |
| //UNUSED2009-05 ScRange XclImpAddressConverter::CreateValidRange( |
| //UNUSED2009-05 const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn ) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 return ScRange( |
| //UNUSED2009-05 CreateValidAddress( rXclRange.maFirst, nScTab1, bWarn ), |
| //UNUSED2009-05 CreateValidAddress( rXclRange.maLast, nScTab2, bWarn ) ); |
| //UNUSED2009-05 } |
| |
| // cell range list ------------------------------------------------------------ |
| |
| //UNUSED2009-05 bool XclImpAddressConverter::CheckRangeList( const XclRangeList& rXclRanges, bool bWarn ) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt ) |
| //UNUSED2009-05 if( !CheckRange( *aIt, bWarn ) ) |
| //UNUSED2009-05 return false; |
| //UNUSED2009-05 return true; |
| //UNUSED2009-05 } |
| |
| void XclImpAddressConverter::ConvertRangeList( ScRangeList& rScRanges, |
| const XclRangeList& rXclRanges, SCTAB nScTab, bool bWarn ) |
| { |
| rScRanges.RemoveAll(); |
| for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt ) |
| { |
| ScRange aScRange( ScAddress::UNINITIALIZED ); |
| if( ConvertRange( aScRange, *aIt, nScTab, nScTab, bWarn ) ) |
| rScRanges.Append( aScRange ); |
| } |
| } |
| |
| // String->EditEngine conversion ============================================== |
| |
| namespace { |
| |
| EditTextObject* lclCreateTextObject( const XclImpRoot& rRoot, |
| const XclImpString& rString, XclFontItemType eType, sal_uInt16 nXFIndex ) |
| { |
| EditTextObject* pTextObj = 0; |
| |
| const XclImpXFBuffer& rXFBuffer = rRoot.GetXFBuffer(); |
| const XclImpFont* pFirstFont = rXFBuffer.GetFont( nXFIndex ); |
| bool bFirstEscaped = pFirstFont && pFirstFont->HasEscapement(); |
| |
| if( rString.IsRich() || bFirstEscaped ) |
| { |
| const XclImpFontBuffer& rFontBuffer = rRoot.GetFontBuffer(); |
| const XclFormatRunVec& rFormats = rString.GetFormats(); |
| |
| ScEditEngineDefaulter& rEE = (eType == EXC_FONTITEM_NOTE) ? |
| static_cast< ScEditEngineDefaulter& >( rRoot.GetDoc().GetNoteEngine() ) : rRoot.GetEditEngine(); |
| rEE.SetText( rString.GetText() ); |
| |
| SfxItemSet aItemSet( rEE.GetEmptyItemSet() ); |
| if( bFirstEscaped ) |
| rFontBuffer.FillToItemSet( aItemSet, eType, rXFBuffer.GetFontIndex( nXFIndex ) ); |
| ESelection aSelection; |
| |
| XclFormatRun aNextRun; |
| XclFormatRunVec::const_iterator aIt = rFormats.begin(); |
| XclFormatRunVec::const_iterator aEnd = rFormats.end(); |
| |
| if( aIt != aEnd ) |
| aNextRun = *aIt++; |
| else |
| aNextRun.mnChar = 0xFFFF; |
| |
| xub_StrLen nLen = rString.GetText().Len(); |
| for( sal_uInt16 nChar = 0; nChar < nLen; ++nChar ) |
| { |
| // reached new different formatted text portion |
| if( nChar >= aNextRun.mnChar ) |
| { |
| // send items to edit engine |
| rEE.QuickSetAttribs( aItemSet, aSelection ); |
| |
| // start new item set |
| aItemSet.ClearItem(); |
| rFontBuffer.FillToItemSet( aItemSet, eType, aNextRun.mnFontIdx ); |
| |
| // read new formatting information |
| if( aIt != aEnd ) |
| aNextRun = *aIt++; |
| else |
| aNextRun.mnChar = 0xFFFF; |
| |
| // reset selection start to current position |
| aSelection.nStartPara = aSelection.nEndPara; |
| aSelection.nStartPos = aSelection.nEndPos; |
| } |
| |
| // set end of selection to current position |
| if( rString.GetText().GetChar( nChar ) == '\n' ) |
| { |
| ++aSelection.nEndPara; |
| aSelection.nEndPos = 0; |
| } |
| else |
| ++aSelection.nEndPos; |
| } |
| |
| // send items of last text portion to edit engine |
| rEE.QuickSetAttribs( aItemSet, aSelection ); |
| |
| pTextObj = rEE.CreateTextObject(); |
| } |
| |
| return pTextObj; |
| } |
| |
| } // namespace |
| |
| EditTextObject* XclImpStringHelper::CreateTextObject( |
| const XclImpRoot& rRoot, const XclImpString& rString ) |
| { |
| return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, 0 ); |
| } |
| |
| //UNUSED2009-05 EditTextObject* XclImpStringHelper::CreateNoteObject( |
| //UNUSED2009-05 const XclImpRoot& rRoot, const XclImpString& rString ) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_NOTE, 0 ); |
| //UNUSED2009-05 } |
| |
| ScBaseCell* XclImpStringHelper::CreateCell( |
| const XclImpRoot& rRoot, const XclImpString& rString, sal_uInt16 nXFIndex ) |
| { |
| ScBaseCell* pCell = 0; |
| |
| if( rString.GetText().Len() ) |
| { |
| ::std::auto_ptr< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, nXFIndex ) ); |
| ScDocument& rDoc = rRoot.GetDoc(); |
| |
| if( pTextObj.get() ) |
| // ScEditCell creates own copy of text object |
| pCell = new ScEditCell( pTextObj.get(), &rDoc, rRoot.GetEditEngine().GetEditTextObjectPool() ); |
| else |
| pCell = ScBaseCell::CreateTextCell( rString.GetText(), &rDoc ); |
| } |
| |
| return pCell; |
| } |
| |
| // Header/footer conversion =================================================== |
| |
| XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() : |
| mnHeight( 0 ), |
| mnMaxLineHt( 0 ) |
| { |
| maSel.nStartPara = maSel.nEndPara = 0; |
| maSel.nStartPos = maSel.nEndPos = 0; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclImpHFConverter::XclImpHFConverter( const XclImpRoot& rRoot ) : |
| XclImpRoot( rRoot ), |
| mrEE( rRoot.GetHFEditEngine() ), |
| mxFontData( new XclFontData ), |
| meCurrObj( EXC_HF_CENTER ) |
| { |
| } |
| |
| XclImpHFConverter::~XclImpHFConverter() |
| { |
| } |
| |
| void XclImpHFConverter::ParseString( const String& rHFString ) |
| { |
| // edit engine objects |
| mrEE.SetText( EMPTY_STRING ); |
| maInfos.clear(); |
| maInfos.resize( EXC_HF_PORTION_COUNT ); |
| meCurrObj = EXC_HF_CENTER; |
| |
| // parser temporaries |
| maCurrText.Erase(); |
| String aReadFont; // current font name |
| String aReadStyle; // current font style |
| sal_uInt16 nReadHeight = 0; // current font height |
| ResetFontData(); |
| |
| /** State of the parser. */ |
| enum XclHFParserState |
| { |
| xlPSText, /// Read text, search for functions. |
| xlPSFunc, /// Read function (token following a '&'). |
| xlPSFont, /// Read font name ('&' is followed by '"', reads until next '"' or ','). |
| xlPSFontStyle, /// Read font style name (font part after ',', reads until next '"'). |
| xlPSHeight /// Read font height ('&' is followed by num. digits, reads until non-digit). |
| } eState = xlPSText; |
| |
| const sal_Unicode* pChar = rHFString.GetBuffer(); |
| const sal_Unicode* pNull = pChar + rHFString.Len(); // pointer to teminating null char |
| while( *pChar ) |
| { |
| switch( eState ) |
| { |
| |
| // --- read text character --- |
| |
| case xlPSText: |
| { |
| switch( *pChar ) |
| { |
| case '&': // new command |
| InsertText(); |
| eState = xlPSFunc; |
| break; |
| case '\n': // line break |
| InsertText(); |
| InsertLineBreak(); |
| break; |
| default: |
| maCurrText += *pChar; |
| } |
| } |
| break; |
| |
| // --- read control sequence --- |
| |
| case xlPSFunc: |
| { |
| eState = xlPSText; |
| switch( *pChar ) |
| { |
| case '&': maCurrText += '&'; break; // the '&' character |
| |
| case 'L': SetNewPortion( EXC_HF_LEFT ); break; // Left portion |
| case 'C': SetNewPortion( EXC_HF_CENTER ); break; // Center portion |
| case 'R': SetNewPortion( EXC_HF_RIGHT ); break; // Right portion |
| |
| case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD ) ); break; // page |
| case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD ) ); break; // page count |
| case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD ) ); break; // date |
| case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD ) ); break; // time |
| case 'A': InsertField( SvxFieldItem( SvxTableField(), EE_FEATURE_FIELD ) ); break; // table name |
| |
| case 'Z': // file path |
| InsertField( SvxFieldItem( SvxExtFileField(), EE_FEATURE_FIELD ) ); // convert to full name |
| if( (pNull - pChar >= 2) && (*(pChar + 1) == '&') && (*(pChar + 2) == 'F') ) |
| { |
| // &Z&F found - ignore the &F part |
| pChar += 2; |
| } |
| break; |
| case 'F': // file name |
| InsertField( SvxFieldItem( SvxExtFileField( EMPTY_STRING, SVXFILETYPE_VAR, SVXFILEFORMAT_NAME_EXT ), EE_FEATURE_FIELD ) ); |
| break; |
| |
| case 'U': // underline |
| SetAttribs(); |
| mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_SINGLE) ? |
| EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_SINGLE; |
| break; |
| case 'E': // double underline |
| SetAttribs(); |
| mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_DOUBLE) ? |
| EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_DOUBLE; |
| break; |
| case 'S': // strikeout |
| SetAttribs(); |
| mxFontData->mbStrikeout = !mxFontData->mbStrikeout; |
| break; |
| case 'X': // superscript |
| SetAttribs(); |
| mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUPER) ? |
| EXC_FONTESC_NONE : EXC_FONTESC_SUPER; |
| break; |
| case 'Y': // subsrcipt |
| SetAttribs(); |
| mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUB) ? |
| EXC_FONTESC_NONE : EXC_FONTESC_SUB; |
| break; |
| |
| case '\"': // font name |
| aReadFont.Erase(); |
| aReadStyle.Erase(); |
| eState = xlPSFont; |
| break; |
| default: |
| if( ('0' <= *pChar) && (*pChar <= '9') ) // font size |
| { |
| nReadHeight = *pChar - '0'; |
| eState = xlPSHeight; |
| } |
| } |
| } |
| break; |
| |
| // --- read font name --- |
| |
| case xlPSFont: |
| { |
| switch( *pChar ) |
| { |
| case '\"': |
| --pChar; |
| // run through |
| case ',': |
| eState = xlPSFontStyle; |
| break; |
| default: |
| aReadFont += *pChar; |
| } |
| } |
| break; |
| |
| // --- read font style --- |
| |
| case xlPSFontStyle: |
| { |
| switch( *pChar ) |
| { |
| case '\"': |
| SetAttribs(); |
| if( aReadFont.Len() ) |
| mxFontData->maName = aReadFont; |
| mxFontData->maStyle = aReadStyle; |
| eState = xlPSText; |
| break; |
| default: |
| aReadStyle += *pChar; |
| } |
| } |
| break; |
| |
| // --- read font height --- |
| |
| case xlPSHeight: |
| { |
| if( ('0' <= *pChar) && (*pChar <= '9') ) |
| { |
| if( nReadHeight != 0xFFFF ) |
| { |
| nReadHeight *= 10; |
| nReadHeight += (*pChar - '0'); |
| if( nReadHeight > 1600 ) // max 1600pt = 32000twips |
| nReadHeight = 0xFFFF; |
| } |
| } |
| else |
| { |
| if( (nReadHeight != 0) && (nReadHeight != 0xFFFF) ) |
| { |
| SetAttribs(); |
| mxFontData->mnHeight = nReadHeight * 20; |
| } |
| --pChar; |
| eState = xlPSText; |
| } |
| } |
| break; |
| } |
| ++pChar; |
| } |
| |
| // finalize |
| CreateCurrObject(); |
| maInfos[ EXC_HF_LEFT ].mnHeight += GetMaxLineHeight( EXC_HF_LEFT ); |
| maInfos[ EXC_HF_CENTER ].mnHeight += GetMaxLineHeight( EXC_HF_CENTER ); |
| maInfos[ EXC_HF_RIGHT ].mnHeight += GetMaxLineHeight( EXC_HF_RIGHT ); |
| } |
| |
| void XclImpHFConverter::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nWhichId ) const |
| { |
| ScPageHFItem aHFItem( nWhichId ); |
| if( maInfos[ EXC_HF_LEFT ].mxObj.get() ) |
| aHFItem.SetLeftArea( *maInfos[ EXC_HF_LEFT ].mxObj ); |
| if( maInfos[ EXC_HF_CENTER ].mxObj.get() ) |
| aHFItem.SetCenterArea( *maInfos[ EXC_HF_CENTER ].mxObj ); |
| if( maInfos[ EXC_HF_RIGHT ].mxObj.get() ) |
| aHFItem.SetRightArea( *maInfos[ EXC_HF_RIGHT ].mxObj ); |
| rItemSet.Put( aHFItem ); |
| } |
| |
| sal_Int32 XclImpHFConverter::GetTotalHeight() const |
| { |
| return ::std::max( maInfos[ EXC_HF_LEFT ].mnHeight, |
| ::std::max( maInfos[ EXC_HF_CENTER ].mnHeight, maInfos[ EXC_HF_RIGHT ].mnHeight ) ); |
| } |
| |
| // private -------------------------------------------------------------------- |
| |
| sal_uInt16 XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion ) const |
| { |
| sal_uInt16 nMaxHt = maInfos[ ePortion ].mnMaxLineHt; |
| return (nMaxHt == 0) ? mxFontData->mnHeight : nMaxHt; |
| } |
| |
| sal_uInt16 XclImpHFConverter::GetCurrMaxLineHeight() const |
| { |
| return GetMaxLineHeight( meCurrObj ); |
| } |
| |
| void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion ) |
| { |
| sal_uInt16& rnMaxHt = maInfos[ ePortion ].mnMaxLineHt; |
| rnMaxHt = ::std::max( rnMaxHt, mxFontData->mnHeight ); |
| } |
| |
| void XclImpHFConverter::UpdateCurrMaxLineHeight() |
| { |
| UpdateMaxLineHeight( meCurrObj ); |
| } |
| |
| void XclImpHFConverter::SetAttribs() |
| { |
| ESelection& rSel = GetCurrSel(); |
| if( (rSel.nStartPara != rSel.nEndPara) || (rSel.nStartPos != rSel.nEndPos) ) |
| { |
| SfxItemSet aItemSet( mrEE.GetEmptyItemSet() ); |
| XclImpFont aFont( GetRoot(), *mxFontData ); |
| aFont.FillToItemSet( aItemSet, EXC_FONTITEM_HF ); |
| mrEE.QuickSetAttribs( aItemSet, rSel ); |
| rSel.nStartPara = rSel.nEndPara; |
| rSel.nStartPos = rSel.nEndPos; |
| } |
| } |
| |
| void XclImpHFConverter::ResetFontData() |
| { |
| if( const XclImpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) ) |
| *mxFontData = pFirstFont->GetFontData(); |
| else |
| { |
| mxFontData->Clear(); |
| mxFontData->mnHeight = 200; |
| } |
| } |
| |
| void XclImpHFConverter::InsertText() |
| { |
| if( maCurrText.Len() ) |
| { |
| ESelection& rSel = GetCurrSel(); |
| mrEE.QuickInsertText( maCurrText, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) ); |
| rSel.nEndPos = rSel.nEndPos + maCurrText.Len(); |
| maCurrText.Erase(); |
| UpdateCurrMaxLineHeight(); |
| } |
| } |
| |
| void XclImpHFConverter::InsertField( const SvxFieldItem& rFieldItem ) |
| { |
| ESelection& rSel = GetCurrSel(); |
| mrEE.QuickInsertField( rFieldItem, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) ); |
| ++rSel.nEndPos; |
| UpdateCurrMaxLineHeight(); |
| } |
| |
| void XclImpHFConverter::InsertLineBreak() |
| { |
| ESelection& rSel = GetCurrSel(); |
| mrEE.QuickInsertText( String( '\n' ), ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) ); |
| ++rSel.nEndPara; |
| rSel.nEndPos = 0; |
| GetCurrInfo().mnHeight += GetCurrMaxLineHeight(); |
| GetCurrInfo().mnMaxLineHt = 0; |
| } |
| |
| void XclImpHFConverter::CreateCurrObject() |
| { |
| InsertText(); |
| SetAttribs(); |
| GetCurrObj().reset( mrEE.CreateTextObject() ); |
| } |
| |
| void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew ) |
| { |
| if( eNew != meCurrObj ) |
| { |
| CreateCurrObject(); |
| meCurrObj = eNew; |
| if( GetCurrObj().get() ) |
| mrEE.SetText( *GetCurrObj() ); |
| else |
| mrEE.SetText( EMPTY_STRING ); |
| ResetFontData(); |
| } |
| } |
| |
| // URL conversion ============================================================= |
| |
| namespace { |
| |
| void lclAppendUrlChar( String& rUrl, sal_Unicode cChar ) |
| { |
| // #126855# encode special characters |
| switch( cChar ) |
| { |
| case '#': rUrl.AppendAscii( "%23" ); break; |
| case '%': rUrl.AppendAscii( "%25" ); break; |
| default: rUrl.Append( cChar ); |
| } |
| } |
| |
| } // namespace |
| |
| void XclImpUrlHelper::DecodeUrl( |
| String& rUrl, String& rTabName, bool& rbSameWb, |
| const XclImpRoot& rRoot, const String& rEncodedUrl ) |
| { |
| enum |
| { |
| xlUrlInit, /// Initial state, read string mode character. |
| xlUrlPath, /// Read URL path. |
| xlUrlFileName, /// Read file name. |
| xlUrlSheetName, /// Read sheet name. |
| xlUrlRaw /// Raw mode. No control characters will occur. |
| } eState = xlUrlInit; |
| |
| bool bEncoded = true; |
| rbSameWb = false; |
| |
| sal_Unicode cCurrDrive = 0; |
| String aDosBase( INetURLObject( rRoot.GetBasePath() ).getFSysPath( INetURLObject::FSYS_DOS ) ); |
| if( (aDosBase.Len() > 2) && aDosBase.EqualsAscii( ":\\", 1, 2 ) ) |
| cCurrDrive = aDosBase.GetChar( 0 ); |
| |
| const sal_Unicode* pChar = rEncodedUrl.GetBuffer(); |
| while( *pChar ) |
| { |
| switch( eState ) |
| { |
| |
| // --- first character --- |
| |
| case xlUrlInit: |
| { |
| switch( *pChar ) |
| { |
| case EXC_URLSTART_ENCODED: |
| eState = xlUrlPath; |
| break; |
| case EXC_URLSTART_SELF: |
| case EXC_URLSTART_SELFENCODED: |
| rbSameWb = true; |
| eState = xlUrlSheetName; |
| break; |
| case '[': |
| bEncoded = false; |
| eState = xlUrlFileName; |
| break; |
| default: |
| bEncoded = false; |
| lclAppendUrlChar( rUrl, *pChar ); |
| eState = xlUrlPath; |
| } |
| } |
| break; |
| |
| // --- URL path --- |
| |
| case xlUrlPath: |
| { |
| switch( *pChar ) |
| { |
| case EXC_URL_DOSDRIVE: |
| { |
| if( *(pChar + 1) ) |
| { |
| ++pChar; |
| if( *pChar == '@' ) |
| rUrl.AppendAscii( "\\\\" ); |
| else |
| { |
| lclAppendUrlChar( rUrl, *pChar ); |
| rUrl.AppendAscii( ":\\" ); |
| } |
| } |
| else |
| rUrl.AppendAscii( "<NULL-DRIVE!>" ); |
| } |
| break; |
| case EXC_URL_DRIVEROOT: |
| if( cCurrDrive ) |
| { |
| lclAppendUrlChar( rUrl, cCurrDrive ); |
| rUrl.Append( ':' ); |
| } |
| // run through |
| case EXC_URL_SUBDIR: |
| if( bEncoded ) |
| rUrl.Append( '\\' ); |
| else // control character in raw name -> DDE link |
| { |
| rUrl.Append( EXC_DDE_DELIM ); |
| eState = xlUrlRaw; |
| } |
| break; |
| case EXC_URL_PARENTDIR: |
| rUrl.AppendAscii( "..\\" ); |
| break; |
| case EXC_URL_RAW: |
| { |
| if( *(pChar + 1) ) |
| { |
| xub_StrLen nLen = *++pChar; |
| for( xub_StrLen nChar = 0; (nChar < nLen) && *(pChar + 1); ++nChar ) |
| lclAppendUrlChar( rUrl, *++pChar ); |
| // rUrl.Append( ':' ); |
| } |
| } |
| break; |
| case '[': |
| eState = xlUrlFileName; |
| break; |
| default: |
| lclAppendUrlChar( rUrl, *pChar ); |
| } |
| } |
| break; |
| |
| // --- file name --- |
| |
| case xlUrlFileName: |
| { |
| switch( *pChar ) |
| { |
| case ']': eState = xlUrlSheetName; break; |
| default: lclAppendUrlChar( rUrl, *pChar ); |
| } |
| } |
| break; |
| |
| // --- sheet name --- |
| |
| case xlUrlSheetName: |
| rTabName.Append( *pChar ); |
| break; |
| |
| // --- raw read mode --- |
| |
| case xlUrlRaw: |
| lclAppendUrlChar( rUrl, *pChar ); |
| break; |
| } |
| |
| ++pChar; |
| } |
| } |
| |
| void XclImpUrlHelper::DecodeUrl( |
| String& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const String& rEncodedUrl ) |
| { |
| String aTabName; |
| DecodeUrl( rUrl, aTabName, rbSameWb, rRoot, rEncodedUrl ); |
| DBG_ASSERT( !aTabName.Len(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" ); |
| } |
| |
| bool XclImpUrlHelper::DecodeLink( String& rApplic, String& rTopic, const String rEncUrl ) |
| { |
| xub_StrLen nPos = rEncUrl.Search( EXC_DDE_DELIM ); |
| if( (nPos != STRING_NOTFOUND) && (0 < nPos) && (nPos + 1 < rEncUrl.Len()) ) |
| { |
| rApplic = rEncUrl.Copy( 0, nPos ); |
| rTopic = rEncUrl.Copy( nPos + 1 ); |
| return true; |
| } |
| return false; |
| } |
| |
| // Cached Values ============================================================== |
| |
| XclImpCachedValue::XclImpCachedValue( XclImpStream& rStrm ) : |
| mfValue( 0.0 ), |
| mnBoolErr( 0 ) |
| { |
| rStrm >> mnType; |
| switch( mnType ) |
| { |
| case EXC_CACHEDVAL_EMPTY: |
| rStrm.Ignore( 8 ); |
| break; |
| case EXC_CACHEDVAL_DOUBLE: |
| rStrm >> mfValue; |
| break; |
| case EXC_CACHEDVAL_STRING: |
| mxStr.reset( new String( rStrm.ReadUniString() ) ); |
| break; |
| case EXC_CACHEDVAL_BOOL: |
| case EXC_CACHEDVAL_ERROR: |
| { |
| double fVal; |
| rStrm >> mnBoolErr; |
| rStrm.Ignore( 7 ); |
| |
| const ScTokenArray* pScTokArr = rStrm.GetRoot().GetOldFmlaConverter().GetBoolErr( |
| XclTools::ErrorToEnum( fVal, mnType == EXC_CACHEDVAL_ERROR, mnBoolErr ) ); |
| if( pScTokArr ) |
| mxTokArr.reset( pScTokArr->Clone() ); |
| } |
| break; |
| default: |
| DBG_ERRORFILE( "XclImpCachedValue::XclImpCachedValue - unknown data type" ); |
| } |
| } |
| |
| XclImpCachedValue::~XclImpCachedValue() |
| { |
| } |
| |
| sal_uInt16 XclImpCachedValue::GetScError() const |
| { |
| return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0; |
| } |
| |
| // Matrix Cached Values ============================================================== |
| |
| XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream& rStrm ) : |
| mnScCols( 0 ), |
| mnScRows( 0 ) |
| { |
| mnScCols = rStrm.ReaduInt8(); |
| mnScRows = rStrm.ReaduInt16(); |
| |
| if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 ) |
| { |
| // in BIFF2-BIFF7: 256 columns represented by 0 columns |
| if( mnScCols == 0 ) |
| mnScCols = 256; |
| } |
| else |
| { |
| // in BIFF8: columns and rows decreaed by 1 |
| ++mnScCols; |
| ++mnScRows; |
| } |
| |
| for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow ) |
| for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol ) |
| maValueList.Append( new XclImpCachedValue( rStrm ) ); |
| } |
| |
| XclImpCachedMatrix::~XclImpCachedMatrix() |
| { |
| } |
| |
| ScMatrixRef XclImpCachedMatrix::CreateScMatrix() const |
| { |
| ScMatrixRef xScMatrix; |
| DBG_ASSERT( mnScCols * mnScRows == maValueList.Count(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" ); |
| if( mnScCols && mnScRows && static_cast< sal_uLong >( mnScCols * mnScRows ) <= maValueList.Count() ) |
| { |
| xScMatrix = new ScMatrix( mnScCols, mnScRows ); |
| const XclImpCachedValue* pValue = maValueList.First(); |
| for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow ) |
| { |
| for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol ) |
| { |
| switch( pValue->GetType() ) |
| { |
| case EXC_CACHEDVAL_EMPTY: |
| // Excel shows 0.0 here, not an empty cell |
| xScMatrix->PutEmpty( nScCol, nScRow ); |
| break; |
| case EXC_CACHEDVAL_DOUBLE: |
| xScMatrix->PutDouble( pValue->GetValue(), nScCol, nScRow ); |
| break; |
| case EXC_CACHEDVAL_STRING: |
| xScMatrix->PutString( pValue->GetString(), nScCol, nScRow ); |
| break; |
| case EXC_CACHEDVAL_BOOL: |
| xScMatrix->PutBoolean( pValue->GetBool(), nScCol, nScRow ); |
| break; |
| case EXC_CACHEDVAL_ERROR: |
| xScMatrix->PutError( pValue->GetScError(), nScCol, nScRow ); |
| break; |
| default: |
| DBG_ERRORFILE( "XclImpCachedMatrix::CreateScMatrix - unknown value type" ); |
| xScMatrix->PutEmpty( nScCol, nScRow ); |
| } |
| pValue = maValueList.Next(); |
| } |
| } |
| } |
| return xScMatrix; |
| } |
| |
| // ============================================================================ |
| |