tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / cppu / source / uno / EnvStack.cxx
blobc44fa283f1a5b788ad72e08d2ae38788918bc912
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <uno/environment.hxx>
21 #include <uno/lbnames.h>
23 #include <cppu/EnvDcp.hxx>
24 #include <cppu/Enterable.hxx>
26 #include <osl/thread.h>
27 #include <osl/thread.hxx>
28 #include <o3tl/string_view.hxx>
30 #include <mutex>
31 #include <unordered_map>
33 using namespace com::sun::star;
35 namespace {
37 struct oslThreadIdentifier_equal
39 bool operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const;
44 bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const
46 bool result = s1 == s2;
48 return result;
51 namespace {
53 struct oslThreadIdentifier_hash
55 size_t operator()(oslThreadIdentifier s1) const;
60 size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1) const
62 return s1;
65 typedef std::unordered_map<oslThreadIdentifier,
66 uno_Environment *,
67 oslThreadIdentifier_hash,
68 oslThreadIdentifier_equal> ThreadMap;
70 namespace
72 std::mutex s_threadMap_mutex;
73 ThreadMap s_threadMap;
76 static void s_setCurrent(uno_Environment * pEnv)
78 oslThreadIdentifier threadId = osl::Thread::getCurrentIdentifier();
80 std::scoped_lock guard(s_threadMap_mutex);
81 if (pEnv)
83 s_threadMap[threadId] = pEnv;
85 else
87 ThreadMap::iterator iEnv = s_threadMap.find(threadId);
88 if( iEnv != s_threadMap.end())
89 s_threadMap.erase(iEnv);
93 static uno_Environment * s_getCurrent()
95 uno_Environment * pEnv = nullptr;
97 oslThreadIdentifier threadId = osl::Thread::getCurrentIdentifier();
99 std::scoped_lock guard(s_threadMap_mutex);
100 ThreadMap::iterator iEnv = s_threadMap.find(threadId);
101 if(iEnv != s_threadMap.end())
102 pEnv = iEnv->second;
104 return pEnv;
108 extern "C" void SAL_CALL uno_getCurrentEnvironment(uno_Environment ** ppEnv, rtl_uString * pTypeName) noexcept
110 if (*ppEnv)
112 (*ppEnv)->release(*ppEnv);
113 *ppEnv = nullptr;
116 OUString currPurpose;
118 uno_Environment * pCurrEnv = s_getCurrent();
119 if (pCurrEnv) // no environment means no purpose
120 currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);
122 if (pTypeName && rtl_uString_getLength(pTypeName))
124 OUString envDcp = OUString::unacquired(&pTypeName) + currPurpose;
126 uno_getEnvironment(ppEnv, envDcp.pData, nullptr);
128 else
130 if (pCurrEnv)
132 *ppEnv = pCurrEnv;
133 (*ppEnv)->acquire(*ppEnv);
135 else
137 OUString uno_envDcp(u"" UNO_LB_UNO ""_ustr);
138 uno_getEnvironment(ppEnv, uno_envDcp.pData, nullptr);
143 static OUString s_getPrefix(std::u16string_view str1, std::u16string_view str2)
145 sal_Int32 nIndex1 = 0;
146 sal_Int32 nIndex2 = 0;
147 sal_Int32 sim = 0;
149 std::u16string_view token1;
150 std::u16string_view token2;
154 token1 = o3tl::getToken(str1, 0, ':', nIndex1);
155 token2 = o3tl::getToken(str2, 0, ':', nIndex2);
157 if (token1 == token2)
158 sim += token1.size() + 1;
160 while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1 == token2);
162 OUString result;
164 if (sim)
165 result = str1.substr(0, sim - 1);
167 return result;
170 static int s_getNextEnv(uno_Environment ** ppEnv, uno_Environment * pCurrEnv, uno_Environment * pTargetEnv)
172 int res = 0;
174 std::u16string_view nextPurpose;
176 OUString currPurpose;
177 if (pCurrEnv)
178 currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);
180 OUString targetPurpose;
181 if (pTargetEnv)
182 targetPurpose = cppu::EnvDcp::getPurpose(pTargetEnv->pTypeName);
184 OUString intermPurpose(s_getPrefix(currPurpose, targetPurpose));
185 if (currPurpose.getLength() > intermPurpose.getLength())
187 sal_Int32 idx = currPurpose.lastIndexOf(':');
188 nextPurpose = currPurpose.subView(0, idx);
190 res = -1;
192 else if (intermPurpose.getLength() < targetPurpose.getLength())
194 sal_Int32 idx = targetPurpose.indexOf(':', intermPurpose.getLength() + 1);
195 if (idx == -1)
196 nextPurpose = targetPurpose;
198 else
199 nextPurpose = targetPurpose.subView(0, idx);
201 res = 1;
204 if (!nextPurpose.empty())
206 OUString next_envDcp = OUString::Concat(UNO_LB_UNO) + nextPurpose;
207 uno_getEnvironment(ppEnv, next_envDcp.pData, nullptr);
209 else
211 if (*ppEnv)
212 (*ppEnv)->release(*ppEnv);
214 *ppEnv = nullptr;
217 return res;
220 extern "C" { static void s_pull(va_list * pParam)
222 uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
223 va_list * pXparam = va_arg(*pParam, va_list *);
225 pCallee(pXparam);
228 static void s_callInto_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
230 cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
231 if (pEnterable)
232 pEnterable->callInto(s_pull, pCallee, pParam);
234 else
235 pCallee(pParam);
238 static void s_callInto(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
240 va_list param;
242 va_start(param, pCallee);
243 s_callInto_v(pEnv, pCallee, &param);
244 va_end(param);
247 static void s_callOut_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
249 cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
250 if (pEnterable)
251 pEnterable->callOut_v(pCallee, pParam);
253 else
254 pCallee(pParam);
257 static void s_callOut(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
259 va_list param;
261 va_start(param, pCallee);
262 s_callOut_v(pEnv, pCallee, &param);
263 va_end(param);
266 static void s_environment_invoke_v(uno_Environment *, uno_Environment *, uno_EnvCallee *, va_list *);
268 extern "C" { static void s_environment_invoke_vv(va_list * pParam)
270 uno_Environment * pCurrEnv = va_arg(*pParam, uno_Environment *);
271 uno_Environment * pTargetEnv = va_arg(*pParam, uno_Environment *);
272 uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
273 va_list * pXparam = va_arg(*pParam, va_list *);
275 s_environment_invoke_v(pCurrEnv, pTargetEnv, pCallee, pXparam);
278 static void s_environment_invoke_v(uno_Environment * pCurrEnv, uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
280 uno_Environment * pNextEnv = nullptr;
281 switch(s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv))
283 case -1:
284 s_setCurrent(pNextEnv);
285 s_callOut(pCurrEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
286 s_setCurrent(pCurrEnv);
287 break;
289 case 0: {
290 uno_Environment * hld = s_getCurrent();
291 s_setCurrent(pCurrEnv);
292 pCallee(pParam);
293 s_setCurrent(hld);
295 break;
297 case 1:
298 s_setCurrent(pNextEnv);
299 s_callInto(pNextEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
300 s_setCurrent(pCurrEnv);
301 break;
304 if (pNextEnv)
305 pNextEnv->release(pNextEnv);
308 extern "C" void SAL_CALL uno_Environment_invoke_v(uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam) noexcept
310 s_environment_invoke_v(s_getCurrent(), pTargetEnv, pCallee, pParam);
313 extern "C" void SAL_CALL uno_Environment_invoke(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...) noexcept
315 va_list param;
317 va_start(param, pCallee);
318 uno_Environment_invoke_v(pEnv, pCallee, &param);
319 va_end(param);
322 extern "C" void SAL_CALL uno_Environment_enter(uno_Environment * pTargetEnv) noexcept
324 uno_Environment * pNextEnv = nullptr;
325 uno_Environment * pCurrEnv = s_getCurrent();
327 int res;
328 while ( (res = s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) != 0)
330 cppu::Enterable * pEnterable;
332 switch(res)
334 case -1:
335 pEnterable = static_cast<cppu::Enterable *>(pCurrEnv->pReserved);
336 if (pEnterable)
337 pEnterable->leave();
338 pCurrEnv->release(pCurrEnv);
339 break;
341 case 1:
342 pNextEnv->acquire(pNextEnv);
343 pEnterable = static_cast<cppu::Enterable *>(pNextEnv->pReserved);
344 if (pEnterable)
345 pEnterable->enter();
346 break;
349 s_setCurrent(pNextEnv);
350 pCurrEnv = pNextEnv;
354 int SAL_CALL uno_Environment_isValid(uno_Environment * pEnv, rtl_uString ** pReason) noexcept
356 int result = 1;
358 OUString typeName(cppu::EnvDcp::getTypeName(pEnv->pTypeName));
359 if (typeName == UNO_LB_UNO)
361 cppu::Enterable * pEnterable = static_cast<cppu::Enterable *>(pEnv->pReserved);
362 if (pEnterable)
363 result = pEnterable->isValid(reinterpret_cast<OUString *>(pReason));
365 else
367 OUString envDcp = UNO_LB_UNO + cppu::EnvDcp::getPurpose(pEnv->pTypeName);
369 uno::Environment env(envDcp);
371 result = env.isValid(reinterpret_cast<OUString *>(pReason));
374 return result;
377 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */