xref: /aoo42x/main/sc/source/filter/excel/xlescher.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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scfilt.hxx"
26 
27 #include "xlescher.hxx"
28 
29 #include <com/sun/star/drawing/XControlShape.hpp>
30 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
31 #include <svx/unoapi.hxx>
32 #include "document.hxx"
33 #include "xestream.hxx"
34 #include "xistream.hxx"
35 #include "xlroot.hxx"
36 #include "xltools.hxx"
37 
38 using ::rtl::OUString;
39 using ::com::sun::star::uno::Reference;
40 using ::com::sun::star::uno::UNO_QUERY;
41 using ::com::sun::star::drawing::XShape;
42 using ::com::sun::star::drawing::XControlShape;
43 using ::com::sun::star::awt::XControlModel;
44 using ::com::sun::star::script::ScriptEventDescriptor;
45 
46 // Structs and classes ========================================================
47 
XclObjId()48 XclObjId::XclObjId() :
49     mnScTab( SCTAB_INVALID ),
50     mnObjId( EXC_OBJ_INVALID_ID )
51 {
52 }
53 
XclObjId(SCTAB nScTab,sal_uInt16 nObjId)54 XclObjId::XclObjId( SCTAB nScTab, sal_uInt16 nObjId ) :
55     mnScTab( nScTab ),
56     mnObjId( nObjId )
57 {
58 }
59 
operator ==(const XclObjId & rL,const XclObjId & rR)60 bool operator==( const XclObjId& rL, const XclObjId& rR )
61 {
62     return (rL.mnScTab == rR.mnScTab) && (rL.mnObjId == rR.mnObjId);
63 }
64 
operator <(const XclObjId & rL,const XclObjId & rR)65 bool operator<( const XclObjId& rL, const XclObjId& rR )
66 {
67     return (rL.mnScTab < rR.mnScTab) || ((rL.mnScTab == rR.mnScTab) && (rL.mnObjId < rR.mnObjId));
68 }
69 
70 // ----------------------------------------------------------------------------
71 
72 namespace {
73 
74 /** Returns the scaling factor to calculate coordinates from twips. */
lclGetTwipsScale(MapUnit eMapUnit)75 double lclGetTwipsScale( MapUnit eMapUnit )
76 {
77     /*  #111027# We cannot use OutputDevice::LogicToLogic() or the XclTools
78         conversion functions to calculate drawing layer coordinates due to
79         Calc's strange definition of a point (1 inch == 72.27 points, instead
80         of 72 points). */
81     double fScale = 1.0;
82     switch( eMapUnit )
83     {
84         case MAP_TWIP:      fScale = 72 / POINTS_PER_INCH;  break;  // Calc twips <-> real twips
85         case MAP_100TH_MM:  fScale = HMM_PER_TWIPS;         break;  // Calc twips <-> 1/100mm
86         default:            DBG_ERRORFILE( "lclGetTwipsScale - map unit not implemented" );
87     }
88     return fScale;
89 }
90 
91 /** Calculates a drawing layer X position (in twips) from an object column position. */
lclGetXFromCol(ScDocument & rDoc,SCTAB nScTab,sal_uInt16 nXclCol,sal_uInt16 nOffset,double fScale)92 long lclGetXFromCol( ScDocument& rDoc, SCTAB nScTab, sal_uInt16 nXclCol, sal_uInt16 nOffset, double fScale )
93 {
94     SCCOL nScCol = static_cast< SCCOL >( nXclCol );
95     return static_cast< long >( fScale * (rDoc.GetColOffset( nScCol, nScTab ) +
96         ::std::min( nOffset / 1024.0, 1.0 ) * rDoc.GetColWidth( nScCol, nScTab )) + 0.5 );
97 }
98 
99 /** Calculates a drawing layer Y position (in twips) from an object row position. */
lclGetYFromRow(ScDocument & rDoc,SCTAB nScTab,sal_uInt16 nXclRow,sal_uInt16 nOffset,double fScale)100 long lclGetYFromRow( ScDocument& rDoc, SCTAB nScTab, sal_uInt16 nXclRow, sal_uInt16 nOffset, double fScale )
101 {
102     SCROW nScRow = static_cast< SCROW >( nXclRow );
103     return static_cast< long >( fScale * (rDoc.GetRowOffset( nScRow, nScTab ) +
104         ::std::min( nOffset / 256.0, 1.0 ) * rDoc.GetRowHeight( nScRow, nScTab )) + 0.5 );
105 }
106 
107 /** Calculates an object column position from a drawing layer X position (in twips). */
lclGetColFromX(ScDocument & rDoc,SCTAB nScTab,sal_uInt16 & rnXclCol,sal_uInt16 & rnOffset,sal_uInt16 nXclStartCol,sal_uInt16 nXclMaxCol,long & rnStartW,long nX,double fScale)108 void lclGetColFromX(
109         ScDocument& rDoc, SCTAB nScTab, sal_uInt16& rnXclCol,
110         sal_uInt16& rnOffset, sal_uInt16 nXclStartCol, sal_uInt16 nXclMaxCol,
111         long& rnStartW, long nX, double fScale )
112 {
113     // rnStartW in conjunction with nXclStartCol is used as buffer for previously calculated width
114     long nTwipsX = static_cast< long >( nX / fScale + 0.5 );
115     long nColW = 0;
116     for( rnXclCol = nXclStartCol; rnXclCol <= nXclMaxCol; ++rnXclCol )
117     {
118         nColW = rDoc.GetColWidth( static_cast< SCCOL >( rnXclCol ), nScTab );
119         if( rnStartW + nColW > nTwipsX )
120             break;
121         rnStartW += nColW;
122     }
123     rnOffset = nColW ? static_cast< sal_uInt16 >( (nTwipsX - rnStartW) * 1024.0 / nColW + 0.5 ) : 0;
124 }
125 
126 /** Calculates an object row position from a drawing layer Y position (in twips). */
lclGetRowFromY(ScDocument & rDoc,SCTAB nScTab,sal_uInt16 & rnXclRow,sal_uInt16 & rnOffset,sal_uInt16 nXclStartRow,sal_uInt16 nXclMaxRow,long & rnStartH,long nY,double fScale)127 void lclGetRowFromY(
128         ScDocument& rDoc, SCTAB nScTab, sal_uInt16& rnXclRow,
129         sal_uInt16& rnOffset, sal_uInt16 nXclStartRow, sal_uInt16 nXclMaxRow,
130         long& rnStartH, long nY, double fScale )
131 {
132     // rnStartH in conjunction with nXclStartRow is used as buffer for previously calculated height
133     long nTwipsY = static_cast< long >( nY / fScale + 0.5 );
134     long nRowH = 0;
135     bool bFound = false;
136     for( SCROW nRow = static_cast< SCROW >( nXclStartRow ); nRow <= nXclMaxRow; ++nRow )
137     {
138         nRowH = rDoc.GetRowHeight( nRow, nScTab );
139         if( rnStartH + nRowH > nTwipsY )
140         {
141             rnXclRow = static_cast< sal_uInt16 >( nRow );
142             bFound = true;
143             break;
144         }
145         rnStartH += nRowH;
146     }
147     if( !bFound )
148         rnXclRow = nXclMaxRow;
149     rnOffset = static_cast< sal_uInt16 >( nRowH ? ((nTwipsY - rnStartH) * 256.0 / nRowH + 0.5) : 0 );
150 }
151 
152 /** Mirrors a rectangle (from LTR to RTL layout or vice versa). */
lclMirrorRectangle(Rectangle & rRect)153 void lclMirrorRectangle( Rectangle& rRect )
154 {
155     long nLeft = rRect.Left();
156     rRect.Left() = -rRect.Right();
157     rRect.Right() = -nLeft;
158 }
159 
lclGetEmbeddedScale(long nPageSize,sal_Int32 nPageScale,long nPos,double fPosScale)160 sal_uInt16 lclGetEmbeddedScale( long nPageSize, sal_Int32 nPageScale, long nPos, double fPosScale )
161 {
162     return static_cast< sal_uInt16 >( nPos * fPosScale / nPageSize * nPageScale + 0.5 );
163 }
164 
165 } // namespace
166 
167 // ----------------------------------------------------------------------------
168 
XclObjAnchor()169 XclObjAnchor::XclObjAnchor() :
170     mnLX( 0 ),
171     mnTY( 0 ),
172     mnRX( 0 ),
173     mnBY( 0 )
174 {
175 }
176 
GetRect(const XclRoot & rRoot,SCTAB nScTab,MapUnit eMapUnit) const177 Rectangle XclObjAnchor::GetRect( const XclRoot& rRoot, SCTAB nScTab, MapUnit eMapUnit ) const
178 {
179     ScDocument& rDoc = rRoot.GetDoc();
180     double fScale = lclGetTwipsScale( eMapUnit );
181     Rectangle aRect(
182         lclGetXFromCol( rDoc, nScTab, maFirst.mnCol, mnLX, fScale ),
183         lclGetYFromRow( rDoc, nScTab, maFirst.mnRow, mnTY, fScale ),
184         lclGetXFromCol( rDoc, nScTab, maLast.mnCol,  mnRX + 1, fScale ),
185         lclGetYFromRow( rDoc, nScTab, maLast.mnRow,  mnBY, fScale ) );
186 
187     // #106948# adjust coordinates in mirrored sheets
188     if( rDoc.IsLayoutRTL( nScTab ) )
189         lclMirrorRectangle( aRect );
190     return aRect;
191 }
192 
SetRect(const XclRoot & rRoot,SCTAB nScTab,const Rectangle & rRect,MapUnit eMapUnit)193 void XclObjAnchor::SetRect( const XclRoot& rRoot, SCTAB nScTab, const Rectangle& rRect, MapUnit eMapUnit )
194 {
195     ScDocument& rDoc = rRoot.GetDoc();
196     sal_uInt16 nXclMaxCol = rRoot.GetXclMaxPos().Col();
197     sal_uInt16 nXclMaxRow = static_cast<sal_uInt16>( rRoot.GetXclMaxPos().Row());
198 
199     // #106948# adjust coordinates in mirrored sheets
200     Rectangle aRect( rRect );
201     if( rDoc.IsLayoutRTL( nScTab ) )
202         lclMirrorRectangle( aRect );
203 
204     double fScale = lclGetTwipsScale( eMapUnit );
205     long nDummy = 0;
206     lclGetColFromX( rDoc, nScTab, maFirst.mnCol, mnLX, 0,             nXclMaxCol, nDummy, aRect.Left(),   fScale );
207     lclGetColFromX( rDoc, nScTab, maLast.mnCol,  mnRX, maFirst.mnCol, nXclMaxCol, nDummy, aRect.Right(),  fScale );
208     nDummy = 0;
209     lclGetRowFromY( rDoc, nScTab, maFirst.mnRow, mnTY, 0,             nXclMaxRow, nDummy, aRect.Top(),    fScale );
210     lclGetRowFromY( rDoc, nScTab, maLast.mnRow,  mnBY, maFirst.mnRow, nXclMaxRow, nDummy, aRect.Bottom(), fScale );
211 }
212 
SetRect(const Size & rPageSize,sal_Int32 nScaleX,sal_Int32 nScaleY,const Rectangle & rRect,MapUnit eMapUnit,bool bDffAnchor)213 void XclObjAnchor::SetRect( const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY,
214         const Rectangle& rRect, MapUnit eMapUnit, bool bDffAnchor )
215 {
216     double fScale = 1.0;
217     switch( eMapUnit )
218     {
219         case MAP_TWIP:      fScale = HMM_PER_TWIPS; break;  // Calc twips -> 1/100mm
220         case MAP_100TH_MM:  fScale = 1.0;           break;  // Calc 1/100mm -> 1/100mm
221         default:            DBG_ERRORFILE( "XclObjAnchor::SetRect - map unit not implemented" );
222     }
223 
224     /*  In objects with DFF client anchor, the position of the shape is stored
225         in the cell address components of the client anchor. In old BIFF3-BIFF5
226         objects, the position is stored in the offset components of the anchor. */
227     (bDffAnchor ? maFirst.mnCol : mnLX) = lclGetEmbeddedScale( rPageSize.Width(),  nScaleX, rRect.Left(),   fScale );
228     (bDffAnchor ? maFirst.mnRow : mnTY) = lclGetEmbeddedScale( rPageSize.Height(), nScaleY, rRect.Top(),    fScale );
229     (bDffAnchor ? maLast.mnCol  : mnRX) = lclGetEmbeddedScale( rPageSize.Width(),  nScaleX, rRect.Right(),  fScale );
230     (bDffAnchor ? maLast.mnRow  : mnBY) = lclGetEmbeddedScale( rPageSize.Height(), nScaleY, rRect.Bottom(), fScale );
231 
232     // for safety, clear the other members
233     if( bDffAnchor )
234         mnLX = mnTY = mnRX = mnBY = 0;
235     else
236         Set( 0, 0, 0, 0 );
237 }
238 
239 // ----------------------------------------------------------------------------
240 
XclObjLineData()241 XclObjLineData::XclObjLineData() :
242     mnColorIdx( EXC_OBJ_LINE_AUTOCOLOR ),
243     mnStyle( EXC_OBJ_LINE_SOLID ),
244     mnWidth( EXC_OBJ_LINE_HAIR ),
245     mnAuto( EXC_OBJ_LINE_AUTO )
246 {
247 }
248 
operator >>(XclImpStream & rStrm,XclObjLineData & rLineData)249 XclImpStream& operator>>( XclImpStream& rStrm, XclObjLineData& rLineData )
250 {
251     return rStrm
252         >> rLineData.mnColorIdx
253         >> rLineData.mnStyle
254         >> rLineData.mnWidth
255         >> rLineData.mnAuto;
256 }
257 
258 // ----------------------------------------------------------------------------
259 
XclObjFillData()260 XclObjFillData::XclObjFillData() :
261     mnBackColorIdx( EXC_OBJ_LINE_AUTOCOLOR ),
262     mnPattColorIdx( EXC_OBJ_FILL_AUTOCOLOR ),
263     mnPattern( EXC_PATT_SOLID ),
264     mnAuto( EXC_OBJ_FILL_AUTO )
265 {
266 }
267 
operator >>(XclImpStream & rStrm,XclObjFillData & rFillData)268 XclImpStream& operator>>( XclImpStream& rStrm, XclObjFillData& rFillData )
269 {
270     return rStrm
271         >> rFillData.mnBackColorIdx
272         >> rFillData.mnPattColorIdx
273         >> rFillData.mnPattern
274         >> rFillData.mnAuto;
275 }
276 
277 // ----------------------------------------------------------------------------
278 
XclObjTextData()279 XclObjTextData::XclObjTextData() :
280     mnTextLen( 0 ),
281     mnFormatSize( 0 ),
282     mnLinkSize( 0 ),
283     mnDefFontIdx( EXC_FONT_APP ),
284     mnFlags( 0 ),
285     mnOrient( EXC_OBJ_ORIENT_NONE ),
286     mnButtonFlags( 0 ),
287     mnShortcut( 0 ),
288     mnShortcutEA( 0 )
289 {
290 }
291 
ReadObj3(XclImpStream & rStrm)292 void XclObjTextData::ReadObj3( XclImpStream& rStrm )
293 {
294     rStrm >> mnTextLen;
295     rStrm.Ignore( 2 );
296     rStrm >> mnFormatSize >> mnDefFontIdx;
297     rStrm.Ignore( 2 );
298     rStrm >> mnFlags >> mnOrient;
299     rStrm.Ignore( 8 );
300 }
301 
ReadObj5(XclImpStream & rStrm)302 void XclObjTextData::ReadObj5( XclImpStream& rStrm )
303 {
304     rStrm >> mnTextLen;
305     rStrm.Ignore( 2 );
306     rStrm >> mnFormatSize >> mnDefFontIdx;
307     rStrm.Ignore( 2 );
308     rStrm >> mnFlags >> mnOrient;
309     rStrm.Ignore( 2 );
310     rStrm >> mnLinkSize;
311     rStrm.Ignore( 2 );
312     rStrm >> mnButtonFlags >> mnShortcut >> mnShortcutEA;
313 }
314 
ReadTxo8(XclImpStream & rStrm)315 void XclObjTextData::ReadTxo8( XclImpStream& rStrm )
316 {
317     rStrm >> mnFlags >> mnOrient >> mnButtonFlags >> mnShortcut >> mnShortcutEA >> mnTextLen >> mnFormatSize;
318 }
319 
320 // ============================================================================
321 
GetControlModel(Reference<XShape> xShape)322 Reference< XControlModel > XclControlHelper::GetControlModel( Reference< XShape > xShape )
323 {
324     Reference< XControlModel > xCtrlModel;
325     Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY );
326     if( xCtrlShape.is() )
327         xCtrlModel = xCtrlShape->getControl();
328     return xCtrlModel;
329 }
330 
331 namespace {
332 
333 static const struct
334 {
335     const sal_Char*     mpcListenerType;
336     const sal_Char*     mpcEventMethod;
337 }
338 spTbxListenerData[] =
339 {
340     // Attention: MUST be in order of the XclTbxEventType enum!
341     /*EXC_TBX_EVENT_ACTION*/    { "XActionListener",     "actionPerformed"        },
342     /*EXC_TBX_EVENT_MOUSE*/     { "XMouseListener",      "mouseReleased"          },
343     /*EXC_TBX_EVENT_TEXT*/      { "XTextListener",       "textChanged"            },
344     /*EXC_TBX_EVENT_VALUE*/     { "XAdjustmentListener", "adjustmentValueChanged" },
345     /*EXC_TBX_EVENT_CHANGE*/    { "XChangeListener",     "changed"                }
346 };
347 
348 } // namespace
349 
FillMacroDescriptor(ScriptEventDescriptor & rDescriptor,XclTbxEventType eEventType,const String & rXclMacroName,SfxObjectShell * pDocShell)350 bool XclControlHelper::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor,
351         XclTbxEventType eEventType, const String& rXclMacroName, SfxObjectShell* pDocShell )
352 {
353     if( rXclMacroName.Len() > 0 )
354     {
355         rDescriptor.ListenerType = OUString::createFromAscii( spTbxListenerData[ eEventType ].mpcListenerType );
356         rDescriptor.EventMethod = OUString::createFromAscii( spTbxListenerData[ eEventType ].mpcEventMethod );
357         rDescriptor.ScriptType = CREATE_OUSTRING( "Script" );
358         rDescriptor.ScriptCode = XclTools::GetSbMacroUrl( rXclMacroName, pDocShell );
359         return true;
360     }
361     return false;
362 }
363 
ExtractFromMacroDescriptor(const ScriptEventDescriptor & rDescriptor,XclTbxEventType eEventType)364 String XclControlHelper::ExtractFromMacroDescriptor(
365         const ScriptEventDescriptor& rDescriptor, XclTbxEventType eEventType )
366 {
367     if( (rDescriptor.ScriptCode.getLength() > 0) &&
368             rDescriptor.ScriptType.equalsIgnoreAsciiCaseAscii( "Script" ) &&
369             rDescriptor.ListenerType.equalsAscii( spTbxListenerData[ eEventType ].mpcListenerType ) &&
370             rDescriptor.EventMethod.equalsAscii( spTbxListenerData[ eEventType ].mpcEventMethod ) )
371         return XclTools::GetXclMacroName( rDescriptor.ScriptCode );
372     return String::EmptyString();
373 }
374 
375 // ============================================================================
376