xref: /AOO41X/main/oox/source/xls/commentsbuffer.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "oox/xls/commentsbuffer.hxx"
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir #include <com/sun/star/sheet/XSheetAnnotationAnchor.hpp>
31*cdf0e10cSrcweir #include <com/sun/star/sheet/XSheetAnnotationShapeSupplier.hpp>
32*cdf0e10cSrcweir #include <com/sun/star/sheet/XSheetAnnotations.hpp>
33*cdf0e10cSrcweir #include <com/sun/star/sheet/XSheetAnnotationsSupplier.hpp>
34*cdf0e10cSrcweir #include "oox/helper/attributelist.hxx"
35*cdf0e10cSrcweir #include "oox/vml/vmlshape.hxx"
36*cdf0e10cSrcweir #include "oox/xls/addressconverter.hxx"
37*cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx"
38*cdf0e10cSrcweir #include "oox/xls/drawingfragment.hxx"
39*cdf0e10cSrcweir #include "oox/xls/drawingmanager.hxx"
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir namespace oox {
42*cdf0e10cSrcweir namespace xls {
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir // ============================================================================
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir using namespace ::com::sun::star::drawing;
47*cdf0e10cSrcweir using namespace ::com::sun::star::sheet;
48*cdf0e10cSrcweir using namespace ::com::sun::star::table;
49*cdf0e10cSrcweir using namespace ::com::sun::star::text;
50*cdf0e10cSrcweir using namespace ::com::sun::star::uno;
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir using ::rtl::OUString;
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir // ============================================================================
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir namespace {
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir const sal_uInt16 BIFF_NOTE_VISIBLE          = 0x0002;
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir } // namespace
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir // ============================================================================
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir CommentModel::CommentModel() :
65*cdf0e10cSrcweir     mnAuthorId( -1 ),
66*cdf0e10cSrcweir     mnObjId( BIFF_OBJ_INVALID_ID ),
67*cdf0e10cSrcweir     mbVisible( false )
68*cdf0e10cSrcweir {
69*cdf0e10cSrcweir }
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir // ----------------------------------------------------------------------------
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir Comment::Comment( const WorksheetHelper& rHelper ) :
74*cdf0e10cSrcweir     WorksheetHelper( rHelper )
75*cdf0e10cSrcweir {
76*cdf0e10cSrcweir }
77*cdf0e10cSrcweir 
78*cdf0e10cSrcweir void Comment::importComment( const AttributeList& rAttribs )
79*cdf0e10cSrcweir {
80*cdf0e10cSrcweir     maModel.mnAuthorId = rAttribs.getInteger( XML_authorId, -1 );
81*cdf0e10cSrcweir     // cell range will be checked while inserting the comment into the document
82*cdf0e10cSrcweir     getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex() );
83*cdf0e10cSrcweir }
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir void Comment::importComment( SequenceInputStream& rStrm )
86*cdf0e10cSrcweir {
87*cdf0e10cSrcweir     BinRange aBinRange;
88*cdf0e10cSrcweir     rStrm >> maModel.mnAuthorId >> aBinRange;
89*cdf0e10cSrcweir     // cell range will be checked while inserting the comment into the document
90*cdf0e10cSrcweir     getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, aBinRange, getSheetIndex() );
91*cdf0e10cSrcweir }
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir void Comment::importNote( BiffInputStream& rStrm )
94*cdf0e10cSrcweir {
95*cdf0e10cSrcweir     BinAddress aBinAddr;
96*cdf0e10cSrcweir     rStrm >> aBinAddr;
97*cdf0e10cSrcweir     // cell range will be checked while inserting the comment into the document
98*cdf0e10cSrcweir     getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, BinRange( aBinAddr ), getSheetIndex() );
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir     // remaining record data is BIFF dependent
101*cdf0e10cSrcweir     switch( getBiff() )
102*cdf0e10cSrcweir     {
103*cdf0e10cSrcweir         case BIFF2:
104*cdf0e10cSrcweir         case BIFF3:
105*cdf0e10cSrcweir             importNoteBiff2( rStrm );
106*cdf0e10cSrcweir         break;
107*cdf0e10cSrcweir         case BIFF4:
108*cdf0e10cSrcweir         case BIFF5:
109*cdf0e10cSrcweir             importNoteBiff2( rStrm );
110*cdf0e10cSrcweir             // in BIFF4 and BIFF5, comments can have an associated sound
111*cdf0e10cSrcweir             if( (rStrm.getNextRecId() == BIFF_ID_NOTESOUND) && rStrm.startNextRecord() )
112*cdf0e10cSrcweir                 importNoteSound( rStrm );
113*cdf0e10cSrcweir         break;
114*cdf0e10cSrcweir         case BIFF8:
115*cdf0e10cSrcweir             importNoteBiff8( rStrm );
116*cdf0e10cSrcweir         break;
117*cdf0e10cSrcweir         case BIFF_UNKNOWN:
118*cdf0e10cSrcweir         break;
119*cdf0e10cSrcweir     }
120*cdf0e10cSrcweir }
121*cdf0e10cSrcweir 
122*cdf0e10cSrcweir RichStringRef Comment::createText()
123*cdf0e10cSrcweir {
124*cdf0e10cSrcweir     maModel.mxText.reset( new RichString( *this ) );
125*cdf0e10cSrcweir     return maModel.mxText;
126*cdf0e10cSrcweir }
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir void Comment::finalizeImport()
129*cdf0e10cSrcweir {
130*cdf0e10cSrcweir     // BIFF12 stores cell range instead of cell address, use first cell of this range
131*cdf0e10cSrcweir     OSL_ENSURE( (maModel.maRange.StartColumn == maModel.maRange.EndColumn) &&
132*cdf0e10cSrcweir         (maModel.maRange.StartRow == maModel.maRange.EndRow),
133*cdf0e10cSrcweir         "Comment::finalizeImport - comment anchor should be a single cell" );
134*cdf0e10cSrcweir     CellAddress aNotePos( maModel.maRange.Sheet, maModel.maRange.StartColumn, maModel.maRange.StartRow );
135*cdf0e10cSrcweir     if( getAddressConverter().checkCellAddress( aNotePos, true ) && maModel.mxText.get() ) try
136*cdf0e10cSrcweir     {
137*cdf0e10cSrcweir         Reference< XSheetAnnotationsSupplier > xAnnosSupp( getSheet(), UNO_QUERY_THROW );
138*cdf0e10cSrcweir         Reference< XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), UNO_SET_THROW );
139*cdf0e10cSrcweir         // non-empty string required by note implementation (real text will be added below)
140*cdf0e10cSrcweir         xAnnos->insertNew( aNotePos, OUString( sal_Unicode( ' ' ) ) );
141*cdf0e10cSrcweir 
142*cdf0e10cSrcweir         // receive created note from cell (insertNew does not return the note)
143*cdf0e10cSrcweir         Reference< XSheetAnnotationAnchor > xAnnoAnchor( getCell( aNotePos ), UNO_QUERY_THROW );
144*cdf0e10cSrcweir         Reference< XSheetAnnotation > xAnno( xAnnoAnchor->getAnnotation(), UNO_SET_THROW );
145*cdf0e10cSrcweir         Reference< XSheetAnnotationShapeSupplier > xAnnoShapeSupp( xAnno, UNO_QUERY_THROW );
146*cdf0e10cSrcweir         Reference< XShape > xAnnoShape( xAnnoShapeSupp->getAnnotationShape(), UNO_SET_THROW );
147*cdf0e10cSrcweir 
148*cdf0e10cSrcweir         // convert shape formatting and visibility
149*cdf0e10cSrcweir         sal_Bool bVisible = sal_True;
150*cdf0e10cSrcweir         switch( getFilterType() )
151*cdf0e10cSrcweir         {
152*cdf0e10cSrcweir             case FILTER_OOXML:
153*cdf0e10cSrcweir                 if( const ::oox::vml::ShapeBase* pNoteShape = getVmlDrawing().getNoteShape( aNotePos ) )
154*cdf0e10cSrcweir                 {
155*cdf0e10cSrcweir                     // position and formatting
156*cdf0e10cSrcweir                     pNoteShape->convertFormatting( xAnnoShape );
157*cdf0e10cSrcweir                     // visibility
158*cdf0e10cSrcweir                     const ::oox::vml::ClientData* pClientData = pNoteShape->getClientData();
159*cdf0e10cSrcweir                     bVisible = pClientData && pClientData->mbVisible;
160*cdf0e10cSrcweir                 }
161*cdf0e10cSrcweir             break;
162*cdf0e10cSrcweir             case FILTER_BIFF:
163*cdf0e10cSrcweir                 bVisible = maModel.mbVisible;
164*cdf0e10cSrcweir             break;
165*cdf0e10cSrcweir             case FILTER_UNKNOWN:
166*cdf0e10cSrcweir             break;
167*cdf0e10cSrcweir         }
168*cdf0e10cSrcweir         xAnno->setIsVisible( bVisible );
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir         // insert text and convert text formatting
171*cdf0e10cSrcweir         maModel.mxText->finalizeImport();
172*cdf0e10cSrcweir         Reference< XText > xAnnoText( xAnnoShape, UNO_QUERY_THROW );
173*cdf0e10cSrcweir         maModel.mxText->convert( xAnnoText );
174*cdf0e10cSrcweir     }
175*cdf0e10cSrcweir     catch( Exception& )
176*cdf0e10cSrcweir     {
177*cdf0e10cSrcweir     }
178*cdf0e10cSrcweir }
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir // private --------------------------------------------------------------------
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir void Comment::importNoteBiff2( BiffInputStream& rStrm )
183*cdf0e10cSrcweir {
184*cdf0e10cSrcweir     sal_uInt16 nTotalLen;
185*cdf0e10cSrcweir     rStrm >> nTotalLen;
186*cdf0e10cSrcweir     sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.getRemaining() ) );
187*cdf0e10cSrcweir     RichStringRef xNoteText = createText();
188*cdf0e10cSrcweir     xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() );
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir     nTotalLen = nTotalLen - nPartLen;   // operator-=() gives compiler warning
191*cdf0e10cSrcweir     while( (nTotalLen > 0) && (rStrm.getNextRecId() == BIFF_ID_NOTE) && rStrm.startNextRecord() )
192*cdf0e10cSrcweir     {
193*cdf0e10cSrcweir         sal_uInt16 nMarker;
194*cdf0e10cSrcweir         rStrm >> nMarker;
195*cdf0e10cSrcweir         rStrm.skip( 2 );
196*cdf0e10cSrcweir         rStrm >> nPartLen;
197*cdf0e10cSrcweir         OSL_ENSURE( nMarker == 0xFFFF, "Comment::importNoteBiff2 - missing continuation NOTE record" );
198*cdf0e10cSrcweir         if( nMarker == 0xFFFF )
199*cdf0e10cSrcweir         {
200*cdf0e10cSrcweir             OSL_ENSURE( nPartLen <= nTotalLen, "Comment::importNoteBiff2 - string too long" );
201*cdf0e10cSrcweir             // call to RichString::importCharArray() appends new text portion
202*cdf0e10cSrcweir             xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() );
203*cdf0e10cSrcweir             nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen );
204*cdf0e10cSrcweir         }
205*cdf0e10cSrcweir         else
206*cdf0e10cSrcweir         {
207*cdf0e10cSrcweir             // seems to be a new note, rewind record, so worksheet fragment loop will find it
208*cdf0e10cSrcweir             rStrm.rewindRecord();
209*cdf0e10cSrcweir             nTotalLen = 0;
210*cdf0e10cSrcweir         }
211*cdf0e10cSrcweir     }
212*cdf0e10cSrcweir }
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir void Comment::importNoteBiff8( BiffInputStream& rStrm )
215*cdf0e10cSrcweir {
216*cdf0e10cSrcweir     sal_uInt16 nFlags;
217*cdf0e10cSrcweir     rStrm >> nFlags >> maModel.mnObjId;
218*cdf0e10cSrcweir     maModel.maAuthor = rStrm.readUniString();
219*cdf0e10cSrcweir     maModel.mbVisible = getFlag( nFlags, BIFF_NOTE_VISIBLE );
220*cdf0e10cSrcweir }
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir void Comment::importNoteSound( BiffInputStream& /*rStrm*/ )
223*cdf0e10cSrcweir {
224*cdf0e10cSrcweir }
225*cdf0e10cSrcweir 
226*cdf0e10cSrcweir // ============================================================================
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir CommentsBuffer::CommentsBuffer( const WorksheetHelper& rHelper ) :
229*cdf0e10cSrcweir     WorksheetHelper( rHelper )
230*cdf0e10cSrcweir {
231*cdf0e10cSrcweir }
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir void CommentsBuffer::appendAuthor( const OUString& rAuthor )
234*cdf0e10cSrcweir {
235*cdf0e10cSrcweir     maAuthors.push_back( rAuthor );
236*cdf0e10cSrcweir }
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir CommentRef CommentsBuffer::createComment()
239*cdf0e10cSrcweir {
240*cdf0e10cSrcweir     CommentRef xComment( new Comment( *this ) );
241*cdf0e10cSrcweir     maComments.push_back( xComment );
242*cdf0e10cSrcweir     return xComment;
243*cdf0e10cSrcweir }
244*cdf0e10cSrcweir 
245*cdf0e10cSrcweir void CommentsBuffer::finalizeImport()
246*cdf0e10cSrcweir {
247*cdf0e10cSrcweir     maComments.forEachMem( &Comment::finalizeImport );
248*cdf0e10cSrcweir }
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir // ============================================================================
251*cdf0e10cSrcweir 
252*cdf0e10cSrcweir } // namespace xls
253*cdf0e10cSrcweir } // namespace oox
254