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 <rtl/instance.hxx>
22 #include <sal/log.hxx>
24 #include <tools/debug.hxx>
25 #include <vcl/errinf.hxx>
31 class TheErrorRegistry
: public rtl::Static
<ErrorRegistry
, TheErrorRegistry
> {};
33 class ErrorStringFactory
36 static bool CreateString(const ErrorInfo
*, OUString
&);
39 bool ErrorStringFactory::CreateString(const ErrorInfo
* pInfo
, OUString
& rStr
)
41 for(const ErrorHandler
*pHdlr
: TheErrorRegistry::get().errorHandlers
)
43 if(pHdlr
->CreateString(pInfo
, rStr
))
49 ErrorRegistry::ErrorRegistry()
54 for(DynamicErrorInfo
*& rp
: ppDynErrInfo
)
58 void ErrorRegistry::RegisterDisplay(BasicDisplayErrorFunc
*aDsp
)
60 ErrorRegistry
&rData
= TheErrorRegistry::get();
61 rData
.bIsWindowDsp
= false;
62 rData
.pDsp
= reinterpret_cast< DisplayFnPtr
>(aDsp
);
65 void ErrorRegistry::RegisterDisplay(WindowDisplayErrorFunc
*aDsp
)
67 ErrorRegistry
&rData
= TheErrorRegistry::get();
68 rData
.bIsWindowDsp
= true;
69 rData
.pDsp
= reinterpret_cast< DisplayFnPtr
>(aDsp
);
72 static void aDspFunc(const OUString
&rErr
, const OUString
&rAction
)
74 SAL_WARN("vcl", "Action: " << rAction
<< " Error: " << rErr
);
77 ErrorHandler::ErrorHandler()
79 ErrorRegistry
&rData
= TheErrorRegistry::get();
80 rData
.errorHandlers
.insert(rData
.errorHandlers
.begin(), this);
83 ErrorRegistry::RegisterDisplay(&aDspFunc
);
86 ErrorHandler::~ErrorHandler()
88 auto &rErrorHandlers
= TheErrorRegistry::get().errorHandlers
;
89 rErrorHandlers
.erase( ::std::remove(rErrorHandlers
.begin(), rErrorHandlers
.end(), this),
90 rErrorHandlers
.end());
93 bool ErrorHandler::GetErrorString(ErrCode nErrCodeId
, OUString
& rErrStr
)
97 if(!nErrCodeId
|| nErrCodeId
== ERRCODE_ABORT
)
100 std::unique_ptr
<ErrorInfo
> pInfo
= ErrorInfo::GetErrorInfo(nErrCodeId
);
102 if (ErrorStringFactory::CreateString(pInfo
.get(),aErr
))
111 DialogMask
ErrorHandler::HandleError(ErrCode nErrCodeId
, weld::Window
*pParent
, DialogMask nFlags
)
113 if (nErrCodeId
== ERRCODE_NONE
|| nErrCodeId
== ERRCODE_ABORT
)
114 return DialogMask::NONE
;
116 ErrorRegistry
&rData
= TheErrorRegistry::get();
117 std::unique_ptr
<ErrorInfo
> pInfo
= ErrorInfo::GetErrorInfo(nErrCodeId
);
120 if (!rData
.contexts
.empty())
122 rData
.contexts
.front()->GetString(pInfo
->GetErrorCode(), aAction
);
124 for(ErrorContext
*pCtx
: rData
.contexts
)
126 if(pCtx
->GetParent())
128 pParent
= pCtx
->GetParent();
134 bool bWarning
= nErrCodeId
.IsWarning();
135 DialogMask nErrFlags
= DialogMask::ButtonDefaultsOk
| DialogMask::ButtonsOk
;
137 nErrFlags
|= DialogMask::MessageWarning
;
139 nErrFlags
|= DialogMask::MessageError
;
141 DynamicErrorInfo
* pDynPtr
= dynamic_cast<DynamicErrorInfo
*>(pInfo
.get());
144 DialogMask nDynFlags
= pDynPtr
->GetDialogMask();
145 if( nDynFlags
!= DialogMask::NONE
)
146 nErrFlags
= nDynFlags
;
150 if (ErrorStringFactory::CreateString(pInfo
.get(), aErr
))
154 SAL_WARN( "vcl", "Action: " << aAction
<< "Error: " << aErr
);
158 if(!rData
.bIsWindowDsp
)
160 (*reinterpret_cast<BasicDisplayErrorFunc
*>(rData
.pDsp
))(aErr
,aAction
);
161 return DialogMask::NONE
;
165 if (nFlags
!= DialogMask::MAX
)
168 return (*reinterpret_cast<WindowDisplayErrorFunc
*>(rData
.pDsp
))(
169 pParent
, nErrFlags
, aErr
, aAction
);
174 SAL_WARN( "vcl", "Error not handled " << pInfo
->GetErrorCode());
175 // Error 1 (ERRCODE_ABORT) is classified as a General Error in sfx
176 if (pInfo
->GetErrorCode() != ERRCODE_ABORT
)
177 HandleError(ERRCODE_ABORT
);
179 OSL_FAIL("ERRCODE_ABORT not handled");
181 return DialogMask::NONE
;
184 struct ImplErrorContext
189 ErrorContext::ErrorContext(weld::Window
*pWinP
)
190 : pImpl( new ImplErrorContext
)
193 TheErrorRegistry::get().contexts
.insert(TheErrorRegistry::get().contexts
.begin(), this);
196 ErrorContext::~ErrorContext()
198 auto &rContexts
= TheErrorRegistry::get().contexts
;
199 rContexts
.erase( ::std::remove(rContexts
.begin(), rContexts
.end(), this), rContexts
.end());
202 ErrorContext
*ErrorContext::GetContext()
204 return TheErrorRegistry::get().contexts
.empty() ? nullptr : TheErrorRegistry::get().contexts
.front();
207 weld::Window
* ErrorContext::GetParent()
209 return pImpl
? pImpl
->pWin
: nullptr;
212 class ImplDynamicErrorInfo
214 friend class DynamicErrorInfo
;
215 friend class ErrorInfo
;
218 explicit ImplDynamicErrorInfo(DialogMask nInMask
)
222 void RegisterError(DynamicErrorInfo
*);
223 static void UnRegisterError(DynamicErrorInfo
const *);
224 static std::unique_ptr
<ErrorInfo
> GetDynamicErrorInfo(ErrCode nId
);
227 DialogMask
const nMask
;
231 void ImplDynamicErrorInfo::RegisterError(DynamicErrorInfo
*pDynErrInfo
)
233 // Register dynamic identifier
234 ErrorRegistry
& rData
= TheErrorRegistry::get();
235 nErrId
= ErrCode(((sal_uInt32(rData
.nNextError
) + 1) << ERRCODE_DYNAMIC_SHIFT
) +
236 sal_uInt32(pDynErrInfo
->GetErrorCode()));
238 if(rData
.ppDynErrInfo
[rData
.nNextError
])
239 delete rData
.ppDynErrInfo
[rData
.nNextError
];
241 rData
.ppDynErrInfo
[rData
.nNextError
] = pDynErrInfo
;
243 if(++rData
.nNextError
>=ERRCODE_DYNAMIC_COUNT
)
247 void ImplDynamicErrorInfo::UnRegisterError(DynamicErrorInfo
const *pDynErrInfo
)
249 DynamicErrorInfo
**ppDynErrInfo
= TheErrorRegistry::get().ppDynErrInfo
;
250 sal_uInt32 nIdx
= ErrCode(*pDynErrInfo
).GetDynamic() - 1;
251 DBG_ASSERT(ppDynErrInfo
[nIdx
] == pDynErrInfo
, "ErrHdl: Error not found");
253 if(ppDynErrInfo
[nIdx
]==pDynErrInfo
)
254 ppDynErrInfo
[nIdx
]=nullptr;
257 std::unique_ptr
<ErrorInfo
> ImplDynamicErrorInfo::GetDynamicErrorInfo(ErrCode nId
)
259 sal_uInt32 nIdx
= nId
.GetDynamic() - 1;
260 DynamicErrorInfo
* pDynErrInfo
= TheErrorRegistry::get().ppDynErrInfo
[nIdx
];
262 if(pDynErrInfo
&& ErrCode(*pDynErrInfo
)==nId
)
263 return std::unique_ptr
<ErrorInfo
>(pDynErrInfo
);
265 return std::make_unique
<ErrorInfo
>(nId
.StripDynamic());
268 std::unique_ptr
<ErrorInfo
> ErrorInfo::GetErrorInfo(ErrCode nId
)
271 return ImplDynamicErrorInfo::GetDynamicErrorInfo(nId
);
273 return std::make_unique
<ErrorInfo
>(nId
);
276 ErrorInfo::~ErrorInfo()
280 DynamicErrorInfo::DynamicErrorInfo(ErrCode nArgUserId
, DialogMask nMask
)
281 : ErrorInfo(nArgUserId
),
282 pImpl(new ImplDynamicErrorInfo(nMask
))
284 pImpl
->RegisterError(this);
287 DynamicErrorInfo::~DynamicErrorInfo()
289 ImplDynamicErrorInfo::UnRegisterError(this);
292 DynamicErrorInfo::operator ErrCode() const
294 return pImpl
->nErrId
;
297 DialogMask
DynamicErrorInfo::GetDialogMask() const
302 StringErrorInfo::StringErrorInfo(
303 ErrCode nArgUserId
, const OUString
& aStringP
, DialogMask nMask
)
304 : DynamicErrorInfo(nArgUserId
, nMask
), aString(aStringP
)
308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */