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