1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <xlescher.hxx>
21 
22 #include <com/sun/star/drawing/XControlShape.hpp>
23 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
24 #include <document.hxx>
25 #include <xistream.hxx>
26 #include <xlroot.hxx>
27 #include <xltools.hxx>
28 
29 using ::com::sun::star::uno::Reference;
30 using ::com::sun::star::uno::UNO_QUERY;
31 using ::com::sun::star::drawing::XShape;
32 using ::com::sun::star::drawing::XControlShape;
33 using ::com::sun::star::awt::XControlModel;
34 using ::com::sun::star::script::ScriptEventDescriptor;
35 
36 namespace {
37 
38 /** Returns the scaling factor to calculate coordinates from twips. */
lclGetTwipsScale(MapUnit eMapUnit)39 double lclGetTwipsScale( MapUnit eMapUnit )
40 {
41     /*  We cannot use OutputDevice::LogicToLogic() or the XclTools
42         conversion functions to calculate drawing layer coordinates due to
43         Calc's strange definition of a point (1 inch == 72.27 points, instead
44         of 72 points).
45         NOTE: Calc's definition changed from TeX points (72.27) to PS points
46         (72), so the MapUnit::MapTwip case now actually also delivers a scale of 1.0
47     */
48     double fScale = 1.0;
49     switch( eMapUnit )
50     {
51         case MapUnit::MapTwip:      fScale = 1;               break;  // Calc twips <-> real twips
52         case MapUnit::Map100thMM:  fScale = HMM_PER_TWIPS;   break;  // Calc twips <-> 1/100mm
53         default:            OSL_FAIL( "lclGetTwipsScale - map unit not implemented" );
54     }
55     return fScale;
56 }
57 
58 /** Calculates a drawing layer X position (in twips) from an object column position. */
lclGetXFromCol(const ScDocument & rDoc,SCTAB nScTab,sal_uInt16 nXclCol,sal_uInt16 nOffset,double fScale)59 long lclGetXFromCol( const ScDocument& rDoc, SCTAB nScTab, sal_uInt16 nXclCol, sal_uInt16 nOffset, double fScale )
60 {
61     SCCOL nScCol = static_cast< SCCOL >( nXclCol );
62     return static_cast< long >( fScale * (rDoc.GetColOffset( nScCol, nScTab ) +
63         ::std::min( nOffset / 1024.0, 1.0 ) * rDoc.GetColWidth( nScCol, nScTab )) + 0.5 );
64 }
65 
66 /** Calculates a drawing layer Y position (in twips) from an object row position. */
lclGetYFromRow(const ScDocument & rDoc,SCTAB nScTab,sal_uInt16 nXclRow,sal_uInt16 nOffset,double fScale)67 long lclGetYFromRow( const ScDocument& rDoc, SCTAB nScTab, sal_uInt16 nXclRow, sal_uInt16 nOffset, double fScale )
68 {
69     SCROW nScRow = static_cast< SCROW >( nXclRow );
70     return static_cast< long >( fScale * (rDoc.GetRowOffset( nScRow, nScTab ) +
71         ::std::min( nOffset / 256.0, 1.0 ) * rDoc.GetRowHeight( nScRow, nScTab )) + 0.5 );
72 }
73 
74 /** Calculates an object column position from a drawing layer X position (in twips). */
lclGetColFromX(const ScDocument & rDoc,SCTAB nScTab,sal_uInt16 & rnXclCol,sal_uInt16 & rnOffset,sal_uInt16 nXclStartCol,sal_uInt16 nXclMaxCol,long & rnStartW,long nX,double fScale)75 void lclGetColFromX(
76         const ScDocument& rDoc, SCTAB nScTab, sal_uInt16& rnXclCol,
77         sal_uInt16& rnOffset, sal_uInt16 nXclStartCol, sal_uInt16 nXclMaxCol,
78         long& rnStartW, long nX, double fScale )
79 {
80     // rnStartW in conjunction with nXclStartCol is used as buffer for previously calculated width
81     long nTwipsX = static_cast< long >( nX / fScale + 0.5 );
82     long nColW = 0;
83     for( rnXclCol = nXclStartCol; rnXclCol <= nXclMaxCol; ++rnXclCol )
84     {
85         nColW = rDoc.GetColWidth( static_cast< SCCOL >( rnXclCol ), nScTab );
86         if( rnStartW + nColW > nTwipsX )
87             break;
88         rnStartW += nColW;
89     }
90     rnOffset = nColW ? static_cast< sal_uInt16 >( (nTwipsX - rnStartW) * 1024.0 / nColW + 0.5 ) : 0;
91 }
92 
93 /** Calculates an object row position from a drawing layer Y position (in twips). */
lclGetRowFromY(const ScDocument & rDoc,SCTAB nScTab,sal_uInt32 & rnXclRow,sal_uInt32 & rnOffset,sal_uInt32 nXclStartRow,sal_uInt32 nXclMaxRow,long & rnStartH,long nY,double fScale)94 void lclGetRowFromY(
95         const ScDocument& rDoc, SCTAB nScTab, sal_uInt32& rnXclRow,
96         sal_uInt32& rnOffset, sal_uInt32 nXclStartRow, sal_uInt32 nXclMaxRow,
97         long& rnStartH, long nY, double fScale )
98 {
99     // rnStartH in conjunction with nXclStartRow is used as buffer for previously calculated height
100     long nTwipsY = static_cast< long >( nY / fScale + 0.5 );
101     long nRowH = 0;
102     bool bFound = false;
103     for( SCROW nRow = static_cast< SCROW >( nXclStartRow ); static_cast<unsigned>(nRow) <= nXclMaxRow; ++nRow )
104     {
105         nRowH = rDoc.GetRowHeight( nRow, nScTab );
106         if( rnStartH + nRowH > nTwipsY )
107         {
108             rnXclRow = static_cast< sal_uInt32 >( nRow );
109             bFound = true;
110             break;
111         }
112         rnStartH += nRowH;
113     }
114     if( !bFound )
115         rnXclRow = nXclMaxRow;
116     rnOffset = static_cast< sal_uInt32 >( nRowH ? ((nTwipsY - rnStartH) * 256.0 / nRowH + 0.5) : 0 );
117 }
118 
119 /** Mirrors a rectangle (from LTR to RTL layout or vice versa). */
lclMirrorRectangle(tools::Rectangle & rRect)120 void lclMirrorRectangle( tools::Rectangle& rRect )
121 {
122     long nLeft = rRect.Left();
123     rRect.SetLeft( -rRect.Right() );
124     rRect.SetRight( -nLeft );
125 }
126 
lclGetEmbeddedScale(long nPageSize,sal_Int32 nPageScale,long nPos,double fPosScale)127 sal_uInt16 lclGetEmbeddedScale( long nPageSize, sal_Int32 nPageScale, long nPos, double fPosScale )
128 {
129     return static_cast< sal_uInt16 >( nPos * fPosScale / nPageSize * nPageScale + 0.5 );
130 }
131 
132 } // namespace
133 
XclObjAnchor()134 XclObjAnchor::XclObjAnchor() :
135     mnLX( 0 ),
136     mnTY( 0 ),
137     mnRX( 0 ),
138     mnBY( 0 )
139 {
140 }
141 
GetRect(const XclRoot & rRoot,SCTAB nScTab,MapUnit eMapUnit) const142 tools::Rectangle XclObjAnchor::GetRect( const XclRoot& rRoot, SCTAB nScTab, MapUnit eMapUnit ) const
143 {
144     ScDocument& rDoc = rRoot.GetDoc();
145     double fScale = lclGetTwipsScale( eMapUnit );
146     tools::Rectangle aRect(
147         lclGetXFromCol(rDoc, nScTab, std::min<SCCOL>(maFirst.mnCol, rDoc.MaxCol()), mnLX, fScale),
148         lclGetYFromRow(rDoc, nScTab, std::min<SCROW>(maFirst.mnRow, rDoc.MaxRow()), mnTY, fScale),
149         lclGetXFromCol(rDoc, nScTab, std::min<SCCOL>(maLast.mnCol, rDoc.MaxCol()),  mnRX + 1, fScale),
150         lclGetYFromRow(rDoc, nScTab, std::min<SCROW>(maLast.mnRow, rDoc.MaxRow()),  mnBY, fScale));
151 
152     // adjust coordinates in mirrored sheets
153     if( rDoc.IsLayoutRTL( nScTab ) )
154         lclMirrorRectangle( aRect );
155     return aRect;
156 }
157 
SetRect(const XclRoot & rRoot,SCTAB nScTab,const tools::Rectangle & rRect,MapUnit eMapUnit)158 void XclObjAnchor::SetRect( const XclRoot& rRoot, SCTAB nScTab, const tools::Rectangle& rRect, MapUnit eMapUnit )
159 {
160     ScDocument& rDoc = rRoot.GetDoc();
161     sal_uInt16 nXclMaxCol = rRoot.GetXclMaxPos().Col();
162     sal_uInt16 nXclMaxRow = static_cast<sal_uInt16>( rRoot.GetXclMaxPos().Row());
163 
164     // adjust coordinates in mirrored sheets
165     tools::Rectangle aRect( rRect );
166     if( rDoc.IsLayoutRTL( nScTab ) )
167         lclMirrorRectangle( aRect );
168 
169     double fScale = lclGetTwipsScale( eMapUnit );
170     long nDummy = 0;
171     lclGetColFromX( rDoc, nScTab, maFirst.mnCol, mnLX, 0,             nXclMaxCol, nDummy, aRect.Left(),   fScale );
172     lclGetColFromX( rDoc, nScTab, maLast.mnCol,  mnRX, maFirst.mnCol, nXclMaxCol, nDummy, aRect.Right(),  fScale );
173     nDummy = 0;
174     lclGetRowFromY( rDoc, nScTab, maFirst.mnRow, mnTY, 0,             nXclMaxRow, nDummy, aRect.Top(),    fScale );
175     lclGetRowFromY( rDoc, nScTab, maLast.mnRow,  mnBY, maFirst.mnRow, nXclMaxRow, nDummy, aRect.Bottom(), fScale );
176 }
177 
SetRect(const Size & rPageSize,sal_Int32 nScaleX,sal_Int32 nScaleY,const tools::Rectangle & rRect,MapUnit eMapUnit)178 void XclObjAnchor::SetRect( const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY,
179         const tools::Rectangle& rRect, MapUnit eMapUnit )
180 {
181     double fScale = 1.0;
182     switch( eMapUnit )
183     {
184         case MapUnit::MapTwip:      fScale = HMM_PER_TWIPS; break;  // Calc twips -> 1/100mm
185         case MapUnit::Map100thMM:  fScale = 1.0;           break;  // Calc 1/100mm -> 1/100mm
186         default:            OSL_FAIL( "XclObjAnchor::SetRect - map unit not implemented" );
187     }
188 
189     /*  In objects with DFF client anchor, the position of the shape is stored
190         in the cell address components of the client anchor. In old BIFF3-BIFF5
191         objects, the position is stored in the offset components of the anchor. */
192     maFirst.mnCol = lclGetEmbeddedScale( rPageSize.Width(),  nScaleX, rRect.Left(),   fScale );
193     maFirst.mnRow = lclGetEmbeddedScale( rPageSize.Height(), nScaleY, rRect.Top(),    fScale );
194     maLast.mnCol = lclGetEmbeddedScale( rPageSize.Width(),  nScaleX, rRect.Right(),  fScale );
195     maLast.mnRow = lclGetEmbeddedScale( rPageSize.Height(), nScaleY, rRect.Bottom(), fScale );
196 
197     // for safety, clear the other members
198     mnLX = mnTY = mnRX = mnBY = 0;
199 }
200 
XclObjLineData()201 XclObjLineData::XclObjLineData() :
202     mnColorIdx( EXC_OBJ_LINE_AUTOCOLOR ),
203     mnStyle( EXC_OBJ_LINE_SOLID ),
204     mnWidth( EXC_OBJ_LINE_HAIR ),
205     mnAuto( EXC_OBJ_LINE_AUTO )
206 {
207 }
208 
operator >>(XclImpStream & rStrm,XclObjLineData & rLineData)209 XclImpStream& operator>>( XclImpStream& rStrm, XclObjLineData& rLineData )
210 {
211     rLineData.mnColorIdx = rStrm.ReaduInt8();
212     rLineData.mnStyle = rStrm.ReaduInt8();
213     rLineData.mnWidth = rStrm.ReaduInt8();
214     rLineData.mnAuto = rStrm.ReaduInt8();
215     return rStrm;
216 }
217 
XclObjFillData()218 XclObjFillData::XclObjFillData() :
219     mnBackColorIdx( EXC_OBJ_LINE_AUTOCOLOR ),
220     mnPattColorIdx( EXC_OBJ_FILL_AUTOCOLOR ),
221     mnPattern( EXC_PATT_SOLID ),
222     mnAuto( EXC_OBJ_FILL_AUTO )
223 {
224 }
225 
operator >>(XclImpStream & rStrm,XclObjFillData & rFillData)226 XclImpStream& operator>>( XclImpStream& rStrm, XclObjFillData& rFillData )
227 {
228     rFillData.mnBackColorIdx = rStrm.ReaduInt8();
229     rFillData.mnPattColorIdx = rStrm.ReaduInt8();
230     rFillData.mnPattern = rStrm.ReaduInt8();
231     rFillData.mnAuto = rStrm.ReaduInt8();
232     return rStrm;
233 }
234 
XclObjTextData()235 XclObjTextData::XclObjTextData() :
236     mnTextLen( 0 ),
237     mnFormatSize( 0 ),
238     mnLinkSize( 0 ),
239     mnDefFontIdx( EXC_FONT_APP ),
240     mnFlags( 0 ),
241     mnOrient( EXC_OBJ_ORIENT_NONE ),
242     mnButtonFlags( 0 ),
243     mnShortcut( 0 ),
244     mnShortcutEA( 0 )
245 {
246 }
247 
ReadObj3(XclImpStream & rStrm)248 void XclObjTextData::ReadObj3( XclImpStream& rStrm )
249 {
250     mnTextLen = rStrm.ReaduInt16();
251     rStrm.Ignore( 2 );
252     mnFormatSize = rStrm.ReaduInt16();
253     mnDefFontIdx = rStrm.ReaduInt16();
254     rStrm.Ignore( 2 );
255     mnFlags = rStrm.ReaduInt16();
256     mnOrient = rStrm.ReaduInt16();
257     rStrm.Ignore( 8 );
258 }
259 
ReadObj5(XclImpStream & rStrm)260 void XclObjTextData::ReadObj5( XclImpStream& rStrm )
261 {
262     mnTextLen = rStrm.ReaduInt16();
263     rStrm.Ignore( 2 );
264     mnFormatSize = rStrm.ReaduInt16();
265     mnDefFontIdx = rStrm.ReaduInt16();
266     rStrm.Ignore( 2 );
267     mnFlags = rStrm.ReaduInt16();
268     mnOrient = rStrm.ReaduInt16();
269     rStrm.Ignore( 2 );
270     mnLinkSize = rStrm.ReaduInt16();
271     rStrm.Ignore( 2 );
272     mnButtonFlags = rStrm.ReaduInt16();
273     mnShortcut = rStrm.ReaduInt16();
274     mnShortcutEA = rStrm.ReaduInt16();
275 }
276 
ReadTxo8(XclImpStream & rStrm)277 void XclObjTextData::ReadTxo8( XclImpStream& rStrm )
278 {
279     mnFlags = rStrm.ReaduInt16();
280     mnOrient = rStrm.ReaduInt16();
281     mnButtonFlags = rStrm.ReaduInt16();
282     mnShortcut = rStrm.ReaduInt16();
283     mnShortcutEA = rStrm.ReaduInt16();
284     mnTextLen = rStrm.ReaduInt16();
285     mnFormatSize = rStrm.ReaduInt16();
286 }
287 
GetControlModel(Reference<XShape> const & xShape)288 Reference< XControlModel > XclControlHelper::GetControlModel( Reference< XShape > const & xShape )
289 {
290     Reference< XControlModel > xCtrlModel;
291     Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY );
292     if( xCtrlShape.is() )
293         xCtrlModel = xCtrlShape->getControl();
294     return xCtrlModel;
295 }
296 
297 namespace {
298 
299 static const struct
300 {
301     const sal_Char*     mpcListenerType;
302     const sal_Char*     mpcEventMethod;
303 }
304 spTbxListenerData[] =
305 {
306     // Attention: MUST be in order of the XclTbxEventType enum!
307     /*EXC_TBX_EVENT_ACTION*/    { "XActionListener",     "actionPerformed"        },
308     /*EXC_TBX_EVENT_MOUSE*/     { "XMouseListener",      "mouseReleased"          },
309     /*EXC_TBX_EVENT_TEXT*/      { "XTextListener",       "textChanged"            },
310     /*EXC_TBX_EVENT_VALUE*/     { "XAdjustmentListener", "adjustmentValueChanged" },
311     /*EXC_TBX_EVENT_CHANGE*/    { "XChangeListener",     "changed"                }
312 };
313 
314 } // namespace
315 
FillMacroDescriptor(ScriptEventDescriptor & rDescriptor,XclTbxEventType eEventType,const OUString & rXclMacroName,SfxObjectShell * pDocShell)316 bool XclControlHelper::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor,
317         XclTbxEventType eEventType, const OUString& rXclMacroName, SfxObjectShell* pDocShell )
318 {
319     if( !rXclMacroName.isEmpty() )
320     {
321         rDescriptor.ListenerType = OUString::createFromAscii( spTbxListenerData[ eEventType ].mpcListenerType );
322         rDescriptor.EventMethod = OUString::createFromAscii( spTbxListenerData[ eEventType ].mpcEventMethod );
323         rDescriptor.ScriptType = "Script";
324         rDescriptor.ScriptCode = XclTools::GetSbMacroUrl( rXclMacroName, pDocShell );
325         return true;
326     }
327     return false;
328 }
329 
ExtractFromMacroDescriptor(const ScriptEventDescriptor & rDescriptor,XclTbxEventType eEventType)330 OUString XclControlHelper::ExtractFromMacroDescriptor(
331         const ScriptEventDescriptor& rDescriptor, XclTbxEventType eEventType )
332 {
333     if( (!rDescriptor.ScriptCode.isEmpty()) &&
334             rDescriptor.ScriptType.equalsIgnoreAsciiCase("Script") &&
335             rDescriptor.ListenerType.equalsAscii( spTbxListenerData[ eEventType ].mpcListenerType ) &&
336             rDescriptor.EventMethod.equalsAscii( spTbxListenerData[ eEventType ].mpcEventMethod ) )
337         return XclTools::GetXclMacroName( rDescriptor.ScriptCode );
338     return OUString();
339 }
340 
341 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
342