1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <osl/diagnose.h>
21 #include <sal/log.hxx>
23 #include <tools/debug.hxx>
25 #include <vcl/errinf.hxx>
34 ErrorRegistry
& GetErrorRegistry()
36 static ErrorRegistry gErrorRegistry
;
37 return gErrorRegistry
;
42 bool ErrorStringFactory::CreateString(const ErrorInfo
* pInfo
, OUString
& rStr
)
44 for(const ErrorHandler
*pHdlr
: GetErrorRegistry().errorHandlers
)
46 if(pHdlr
->CreateString(pInfo
, rStr
))
52 ErrorRegistry::ErrorRegistry()
58 for(DynamicErrorInfo
*& rp
: ppDynErrInfo
)
62 void ErrorRegistry::RegisterDisplay(BasicDisplayErrorFunc
*aDsp
)
64 ErrorRegistry
&rData
= GetErrorRegistry();
65 rData
.bIsWindowDsp
= false;
66 rData
.pDsp
= reinterpret_cast< DisplayFnPtr
>(aDsp
);
69 void ErrorRegistry::RegisterDisplay(WindowDisplayErrorFunc
*aDsp
)
71 ErrorRegistry
&rData
= GetErrorRegistry();
72 rData
.bIsWindowDsp
= true;
73 rData
.pDsp
= reinterpret_cast< DisplayFnPtr
>(aDsp
);
76 void ErrorRegistry::SetLock(bool bLock
)
78 ErrorRegistry
& rData
= GetErrorRegistry();
79 rData
.m_bLock
= bLock
;
82 bool ErrorRegistry::GetLock()
84 ErrorRegistry
& rData
= GetErrorRegistry();
88 void ErrorRegistry::Reset()
90 ErrorRegistry
&rData
= GetErrorRegistry();
91 rData
= ErrorRegistry();
94 static void aDspFunc(const OUString
&rErr
, const OUString
&rAction
)
96 SAL_WARN("vcl", "Action: " << rAction
<< " Error: " << rErr
);
99 ErrorHandler::ErrorHandler()
101 ErrorRegistry
&rData
= GetErrorRegistry();
102 rData
.errorHandlers
.insert(rData
.errorHandlers
.begin(), this);
105 ErrorRegistry::RegisterDisplay(&aDspFunc
);
108 ErrorHandler::~ErrorHandler()
110 auto &rErrorHandlers
= GetErrorRegistry().errorHandlers
;
111 rErrorHandlers
.erase( ::std::remove(rErrorHandlers
.begin(), rErrorHandlers
.end(), this),
112 rErrorHandlers
.end());
115 bool ErrorHandler::GetErrorString(ErrCode nErrCodeId
, OUString
& rErrStr
)
119 if(!nErrCodeId
|| nErrCodeId
== ERRCODE_ABORT
)
122 std::unique_ptr
<ErrorInfo
> pInfo
= ErrorInfo::GetErrorInfo(nErrCodeId
);
124 if (ErrorStringFactory::CreateString(pInfo
.get(),aErr
))
133 DialogMask
ErrorHandler::HandleError(ErrCode nErrCodeId
, weld::Window
*pParent
, DialogMask nFlags
)
135 if (nErrCodeId
== ERRCODE_NONE
|| nErrCodeId
== ERRCODE_ABORT
)
136 return DialogMask::NONE
;
138 ErrorRegistry
&rData
= GetErrorRegistry();
139 std::unique_ptr
<ErrorInfo
> pInfo
= ErrorInfo::GetErrorInfo(nErrCodeId
);
142 if (!rData
.contexts
.empty())
144 rData
.contexts
.front()->GetString(pInfo
->GetErrorCode(), aAction
);
146 for(ErrorContext
*pCtx
: rData
.contexts
)
148 if(pCtx
->GetParent())
150 pParent
= pCtx
->GetParent();
156 bool bWarning
= nErrCodeId
.IsWarning();
157 DialogMask nErrFlags
= DialogMask::ButtonDefaultsOk
| DialogMask::ButtonsOk
;
159 nErrFlags
|= DialogMask::MessageWarning
;
161 nErrFlags
|= DialogMask::MessageError
;
163 DynamicErrorInfo
* pDynPtr
= dynamic_cast<DynamicErrorInfo
*>(pInfo
.get());
166 DialogMask nDynFlags
= pDynPtr
->GetDialogMask();
167 if( nDynFlags
!= DialogMask::NONE
)
168 nErrFlags
= nDynFlags
;
172 if (ErrorStringFactory::CreateString(pInfo
.get(), aErr
))
174 if (!rData
.pDsp
|| rData
.m_bLock
)
176 SAL_WARN( "vcl", "Action: " << aAction
<< "Error: " << aErr
);
180 if(!rData
.bIsWindowDsp
)
182 (*reinterpret_cast<BasicDisplayErrorFunc
*>(rData
.pDsp
))(aErr
,aAction
);
183 return DialogMask::NONE
;
187 if (nFlags
!= DialogMask::MAX
)
190 return (*reinterpret_cast<WindowDisplayErrorFunc
*>(rData
.pDsp
))(
191 pParent
, nErrFlags
, aErr
, aAction
);
196 SAL_WARN( "vcl", "Error not handled " << pInfo
->GetErrorCode());
197 // Error 1 (ERRCODE_ABORT) is classified as a General Error in sfx
198 if (pInfo
->GetErrorCode() != ERRCODE_ABORT
)
199 HandleError(ERRCODE_ABORT
);
201 OSL_FAIL("ERRCODE_ABORT not handled");
203 return DialogMask::NONE
;
206 struct ImplErrorContext
211 ErrorContext::ErrorContext(weld::Window
*pWinP
)
212 : pImpl( new ImplErrorContext
)
215 GetErrorRegistry().contexts
.insert(GetErrorRegistry().contexts
.begin(), this);
218 ErrorContext::~ErrorContext()
220 auto &rContexts
= GetErrorRegistry().contexts
;
221 rContexts
.erase( ::std::remove(rContexts
.begin(), rContexts
.end(), this), rContexts
.end());
224 ErrorContext
*ErrorContext::GetContext()
226 return GetErrorRegistry().contexts
.empty() ? nullptr : GetErrorRegistry().contexts
.front();
229 weld::Window
* ErrorContext::GetParent()
231 return pImpl
? pImpl
->pWin
: nullptr;
234 class ImplDynamicErrorInfo
236 friend class DynamicErrorInfo
;
237 friend class ErrorInfo
;
240 explicit ImplDynamicErrorInfo(DialogMask nInMask
)
244 void RegisterError(DynamicErrorInfo
*);
245 static void UnRegisterError(DynamicErrorInfo
const *);
246 static std::unique_ptr
<ErrorInfo
> GetDynamicErrorInfo(ErrCode nId
);
253 void ImplDynamicErrorInfo::RegisterError(DynamicErrorInfo
*pDynErrInfo
)
255 // Register dynamic identifier
256 ErrorRegistry
& rData
= GetErrorRegistry();
257 nErrId
= ErrCode(((sal_uInt32(rData
.nNextError
) + 1) << ERRCODE_DYNAMIC_SHIFT
) +
258 sal_uInt32(pDynErrInfo
->GetErrorCode()));
260 if(rData
.ppDynErrInfo
[rData
.nNextError
])
261 delete rData
.ppDynErrInfo
[rData
.nNextError
];
263 rData
.ppDynErrInfo
[rData
.nNextError
] = pDynErrInfo
;
265 if(++rData
.nNextError
>=ERRCODE_DYNAMIC_COUNT
)
269 void ImplDynamicErrorInfo::UnRegisterError(DynamicErrorInfo
const *pDynErrInfo
)
271 DynamicErrorInfo
**ppDynErrInfo
= GetErrorRegistry().ppDynErrInfo
;
272 sal_uInt32 nIdx
= ErrCode(*pDynErrInfo
).GetDynamic() - 1;
273 DBG_ASSERT(ppDynErrInfo
[nIdx
] == pDynErrInfo
, "ErrHdl: Error not found");
275 if(ppDynErrInfo
[nIdx
]==pDynErrInfo
)
276 ppDynErrInfo
[nIdx
]=nullptr;
279 std::unique_ptr
<ErrorInfo
> ImplDynamicErrorInfo::GetDynamicErrorInfo(ErrCode nId
)
281 sal_uInt32 nIdx
= nId
.GetDynamic() - 1;
282 DynamicErrorInfo
* pDynErrInfo
= GetErrorRegistry().ppDynErrInfo
[nIdx
];
284 if(pDynErrInfo
&& ErrCode(*pDynErrInfo
)==nId
)
285 return std::unique_ptr
<ErrorInfo
>(pDynErrInfo
);
287 return std::make_unique
<ErrorInfo
>(nId
.StripDynamic());
290 std::unique_ptr
<ErrorInfo
> ErrorInfo::GetErrorInfo(ErrCode nId
)
293 return ImplDynamicErrorInfo::GetDynamicErrorInfo(nId
);
295 return std::make_unique
<ErrorInfo
>(nId
);
298 ErrorInfo::~ErrorInfo()
302 DynamicErrorInfo::DynamicErrorInfo(ErrCode nArgUserId
, DialogMask nMask
)
303 : ErrorInfo(nArgUserId
),
304 pImpl(new ImplDynamicErrorInfo(nMask
))
306 pImpl
->RegisterError(this);
309 DynamicErrorInfo::~DynamicErrorInfo()
311 ImplDynamicErrorInfo::UnRegisterError(this);
314 DynamicErrorInfo::operator ErrCode() const
316 return pImpl
->nErrId
;
319 DialogMask
DynamicErrorInfo::GetDialogMask() const
324 StringErrorInfo::StringErrorInfo(
325 ErrCode nArgUserId
, OUString aStringP
, DialogMask nMask
)
326 : DynamicErrorInfo(nArgUserId
, nMask
), aString(std::move(aStringP
))
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */