xref: /core/sw/source/core/doc/docbasic.cxx (revision 7f50471615fb1b083e6c4735892359d269573e81)
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 <hintids.hxx>
21 
22 #include <rtl/ustring.hxx>
23 #include <sal/log.hxx>
24 #include <vcl/imap.hxx>
25 #include <vcl/imapobj.hxx>
26 #include <basic/sbx.hxx>
27 #include <frmfmt.hxx>
28 #include <fmtinfmt.hxx>
29 #include <fmturl.hxx>
30 #include <frmatr.hxx>
31 #include <doc.hxx>
32 #include <docsh.hxx>
33 #include <swevent.hxx>
34 #include <frameformats.hxx>
35 #include <memory>
36 
37 using namespace ::com::sun::star::uno;
38 
lcl_docbasic_convertArgs(SbxArray & rArgs)39 static std::optional<Sequence<Any>> lcl_docbasic_convertArgs( SbxArray& rArgs )
40 {
41     std::optional<Sequence<Any>> oRet;
42 
43     sal_uInt32 nCount = rArgs.Count();
44     if( nCount > 1 )
45     {
46         nCount--;
47         oRet.emplace( nCount );
48         Any *pUnoArgs = oRet->getArray();
49         for( sal_uInt32 i=0; i<nCount; i++ )
50         {
51             SbxVariable* pVar = rArgs.Get(i + 1);
52             switch( pVar->GetType() )
53             {
54             case SbxSTRING:
55                 pUnoArgs[i] <<= pVar->GetOUString();
56                 break;
57             case SbxCHAR:
58                 pUnoArgs[i] <<= static_cast<sal_Int16>(pVar->GetChar()) ;
59                 break;
60             case SbxUSHORT:
61                 pUnoArgs[i] <<= static_cast<sal_Int16>(pVar->GetUShort());
62                 break;
63             case SbxLONG:
64                 pUnoArgs[i] <<= pVar->GetLong();
65                 break;
66             default:
67                 pUnoArgs[i].clear();
68                 break;
69             }
70         }
71     }
72 
73     return oRet;
74 }
75 
ExecMacro(const SvxMacro & rMacro,OUString * pRet,SbxArray * pArgs)76 void SwDoc::ExecMacro( const SvxMacro& rMacro, OUString* pRet, SbxArray* pArgs )
77 {
78     switch( rMacro.GetScriptType() )
79     {
80     case STARBASIC:
81         {
82             SbxBaseRef aRef;
83             SbxValue* pRetValue = new SbxValue;
84             aRef = pRetValue;
85             mpDocShell->CallBasic( rMacro.GetMacName(),
86                                          rMacro.GetLibName(),
87                                          pArgs, pRet ? pRetValue : nullptr );
88 
89             if( pRet && SbxNULL <  pRetValue->GetType() &&
90                         SbxVOID != pRetValue->GetType() )
91             {
92                 // valid value, so set it
93                 *pRet = pRetValue->GetOUString();
94             }
95         }
96         break;
97     case JAVASCRIPT:
98         // ignore JavaScript calls
99         break;
100     case EXTENDED_STYPE:
101         {
102             std::optional<Sequence<Any> > oUnoArgs;
103             if( pArgs )
104             {
105                 // better to rename the local function to lcl_translateBasic2Uno and
106                 // a much shorter routine can be found in sfx2/source/doc/objmisc.cxx
107                 oUnoArgs = lcl_docbasic_convertArgs( *pArgs );
108             }
109 
110             if (!oUnoArgs)
111             {
112                 oUnoArgs.emplace(0);
113             }
114 
115             // TODO - return value is not handled
116             Any aRet;
117             Sequence< sal_Int16 > aOutArgsIndex;
118             Sequence< Any > aOutArgs;
119 
120             SAL_INFO("sw", "SwDoc::ExecMacro URL is " << rMacro.GetMacName() );
121 
122             mpDocShell->CallXScript(
123                 rMacro.GetMacName(), *oUnoArgs, aRet, aOutArgsIndex, aOutArgs);
124 
125             break;
126         }
127     }
128 }
129 
CallEvent(SvMacroItemId nEvent,const SwCallMouseEvent & rCallEvent,bool bCheckPtr)130 sal_uInt16 SwDoc::CallEvent( SvMacroItemId nEvent, const SwCallMouseEvent& rCallEvent,
131                     bool bCheckPtr )
132 {
133     if( !mpDocShell )        // we can't do that without a DocShell!
134         return 0;
135 
136     sal_uInt16 nRet = 0;
137     const SvxMacroTableDtor* pTable = nullptr;
138     switch( rCallEvent.eType )
139     {
140     case EVENT_OBJECT_INETATTR:
141         if( bCheckPtr  )
142         {
143             ForEachINetFormat(
144                 [&rCallEvent, &bCheckPtr] (const SwFormatINetFormat& rFormatItem) -> bool
145                 {
146                     if( SfxPoolItem::areSame(rCallEvent.PTR.pINetAttr, &rFormatItem) )
147                     {
148                         bCheckPtr = false;       // misuse as a flag
149                         return false;
150                     }
151                     return true;
152                 });
153         }
154         if( !bCheckPtr )
155             pTable = rCallEvent.PTR.pINetAttr->GetMacroTable();
156         break;
157 
158     case EVENT_OBJECT_URLITEM:
159     case EVENT_OBJECT_IMAGE:
160         {
161             const auto pSpz = static_cast<const sw::SpzFrameFormat*>(rCallEvent.PTR.pFormat);
162             if( bCheckPtr )
163             {
164                 if (GetSpzFrameFormats()->IsAlive(pSpz))
165                     bCheckPtr = false;      // misuse as a flag
166                 else
167                     // this shouldn't be possible now that SwCallMouseEvent
168                     // listens for dying format?
169                     assert(false);
170             }
171             if( !bCheckPtr )
172                 pTable = &pSpz->GetMacro().GetMacroTable();
173         }
174         break;
175 
176     case EVENT_OBJECT_IMAGEMAP:
177         {
178             const IMapObject* pIMapObj = rCallEvent.PTR.IMAP.pIMapObj;
179             if( bCheckPtr )
180             {
181                 const auto pSpz = static_cast<const sw::SpzFrameFormat*>(rCallEvent.PTR.IMAP.pFormat);
182                 if (GetSpzFrameFormats()->IsAlive(pSpz))
183                 {
184                     const ImageMap* pIMap = pSpz->GetURL().GetMap();
185                     if (pIMap)
186                     {
187                         for( size_t nPos = pIMap->GetIMapObjectCount(); nPos; )
188                             if( pIMapObj == pIMap->GetIMapObject( --nPos ))
189                             {
190                                 bCheckPtr = false;      // misuse as a flag
191                                 break;
192                             }
193                     }
194                 }
195             }
196             if( !bCheckPtr )
197                 pTable = &pIMapObj->GetMacroTable();
198         }
199         break;
200     default:
201         break;
202     }
203 
204     if( pTable )
205     {
206         nRet = 0x1;
207         if( pTable->IsKeyValid( nEvent ) )
208         {
209             const SvxMacro& rMacro = *pTable->Get( nEvent );
210             if( STARBASIC == rMacro.GetScriptType() )
211             {
212                 nRet += ERRCODE_NONE == mpDocShell->CallBasic( rMacro.GetMacName(),
213                                     rMacro.GetLibName(), nullptr ) ? 1 : 0;
214             }
215             else if( EXTENDED_STYPE == rMacro.GetScriptType() )
216             {
217                 Sequence<Any> aUnoArgs;
218 
219                 Any aRet;
220                 Sequence< sal_Int16 > aOutArgsIndex;
221                 Sequence< Any > aOutArgs;
222 
223                 SAL_INFO("sw", "SwDoc::CallEvent URL is " << rMacro.GetMacName() );
224 
225                 nRet += ERRCODE_NONE == mpDocShell->CallXScript(
226                     rMacro.GetMacName(), aUnoArgs, aRet, aOutArgsIndex, aOutArgs) ? 1 : 0;
227             }
228             // JavaScript calls are ignored
229         }
230     }
231     return nRet;
232 }
233 
234 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
235