blob: befe36f429aa360aa8116a1d053a3b0adc3b2a99 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"
#include <limits.h>
#include <tools/shl.hxx>
#include <tools/debug.hxx>
#include <tools/errinf.hxx>
#include <tools/string.hxx>
class ErrorHandler;
namespace {
typedef void (* DisplayFnPtr)();
}
struct EDcrData
{
public:
ErrorHandler *pFirstHdl;
ErrorContext *pFirstCtx;
DisplayFnPtr pDsp;
sal_Bool bIsWindowDsp;
DynamicErrorInfo *ppDcr[ERRCODE_DYNAMIC_COUNT];
sal_uInt16 nNextDcr;
EDcrData();
static EDcrData *GetData();
};
class EDcr_Impl
{
sal_uIntPtr lErrId;
sal_uInt16 nMask;
void RegisterEDcr(DynamicErrorInfo *);
void UnRegisterEDcr(DynamicErrorInfo *);
static ErrorInfo *GetDynamicErrorInfo(sal_uIntPtr lId);
friend class DynamicErrorInfo;
friend class ErrorInfo;
};
EDcrData::EDcrData()
{
for(sal_uInt16 n=0;n<ERRCODE_DYNAMIC_COUNT;n++)
ppDcr[n]=0;
nNextDcr=0;
pFirstHdl=0;
pDsp=0;
pFirstCtx=0;
}
EDcrData *EDcrData::GetData()
{
#ifdef BOOTSTRAP
return 0x0;
#else
EDcrData **ppDat=(EDcrData **)GetAppData(SHL_ERR);
if(!*ppDat)
{
return (*ppDat=new EDcrData);
}
else
return *ppDat;
#endif
}
void EDcr_Impl::RegisterEDcr(DynamicErrorInfo *pDcr)
{
//Vergibt eine dynamische Id
EDcrData* pData=EDcrData::GetData();
lErrId= (((sal_uIntPtr)pData->nNextDcr + 1) << ERRCODE_DYNAMIC_SHIFT) +
pDcr->GetErrorCode();
DynamicErrorInfo **ppDcr=pData->ppDcr;
sal_uInt16 nNext=pData->nNextDcr;
// bei einem Ringbuffer koennen wir uns das ASSERT wohl sparen!
// DBG_ASSERT(ppDcr[nNext]==0,"ErrHdl: Alle Errors belegt");
if(ppDcr[nNext])
{
delete ppDcr[nNext];
}
ppDcr[nNext]=pDcr;
if(++pData->nNextDcr>=ERRCODE_DYNAMIC_COUNT)
pData->nNextDcr=0;
}
void EDcr_Impl::UnRegisterEDcr(DynamicErrorInfo *pDcr)
{
EDcrData* pData=EDcrData::GetData();
DynamicErrorInfo **ppDcr=pData->ppDcr;
sal_uIntPtr lIdx=(
((sal_uIntPtr)(*pDcr) & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1;
DBG_ASSERT(ppDcr[lIdx]==pDcr,"ErrHdl: Error nicht gefunden");
if(ppDcr[lIdx]==pDcr)
ppDcr[lIdx]=0;
}
TYPEINIT0(ErrorInfo);
TYPEINIT1(DynamicErrorInfo, ErrorInfo);
TYPEINIT1(StandardErrorInfo, DynamicErrorInfo);
TYPEINIT1(StringErrorInfo, DynamicErrorInfo);
TYPEINIT1(TwoStringErrorInfo, DynamicErrorInfo);
TYPEINIT1(MessageInfo, DynamicErrorInfo);
ErrorInfo *ErrorInfo::GetErrorInfo(sal_uIntPtr lId)
{
if(lId & ERRCODE_DYNAMIC_MASK)
return EDcr_Impl::GetDynamicErrorInfo(lId);
else
return new ErrorInfo(lId);
}
DynamicErrorInfo::operator sal_uIntPtr() const
{
return pImpl->lErrId;
}
DynamicErrorInfo::DynamicErrorInfo(sal_uIntPtr lArgUserId, sal_uInt16 nMask)
: ErrorInfo(lArgUserId)
{
pImpl=new EDcr_Impl;
pImpl->RegisterEDcr(this);
pImpl->nMask=nMask;
}
DynamicErrorInfo::~DynamicErrorInfo()
{
pImpl->UnRegisterEDcr(this);
delete pImpl;
}
ErrorInfo* EDcr_Impl::GetDynamicErrorInfo(sal_uIntPtr lId)
{
sal_uIntPtr lIdx=((lId & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1;
DynamicErrorInfo* pDcr=EDcrData::GetData()->ppDcr[lIdx];
if(pDcr && (sal_uIntPtr)(*pDcr)==lId)
return pDcr;
else
return new ErrorInfo(lId & ~ERRCODE_DYNAMIC_MASK);
}
sal_uInt16 DynamicErrorInfo::GetDialogMask() const
{
return pImpl->nMask;
}
StandardErrorInfo::StandardErrorInfo(
sal_uIntPtr UserId, sal_uIntPtr lArgExtId, sal_uInt16 nFlags)
: DynamicErrorInfo(UserId, nFlags), lExtId(lArgExtId)
{
}
StringErrorInfo::StringErrorInfo(
sal_uIntPtr UserId, const String& aStringP, sal_uInt16 nFlags)
: DynamicErrorInfo(UserId, nFlags), aString(aStringP)
{
}
class ErrHdl_Impl
{
public:
ErrorHandler *pNext;
static sal_Bool CreateString(const ErrorHandler *pStart,
const ErrorInfo*, String&, sal_uInt16&);
};
static void aDspFunc(const String &rErr, const String &rAction)
{
ByteString aErr("Aktion: ");
aErr+= ByteString( rAction, RTL_TEXTENCODING_ASCII_US );
aErr+=" Fehler: ";
aErr+= ByteString( rErr, RTL_TEXTENCODING_ASCII_US );
DBG_ERROR(aErr.GetBuffer());
}
ErrorContext::ErrorContext(Window *pWinP)
{
EDcrData *pData=EDcrData::GetData();
ErrorContext *&pHdl=pData->pFirstCtx;
pWin=pWinP;
pNext=pHdl;
pHdl=this;
}
ErrorContext::~ErrorContext()
{
ErrorContext **ppCtx=&(EDcrData::GetData()->pFirstCtx);
while(*ppCtx && *ppCtx!=this)
ppCtx=&((*ppCtx)->pNext);
if(*ppCtx)
*ppCtx=(*ppCtx)->pNext;
}
ErrorContext *ErrorContext::GetContext()
{
return EDcrData::GetData()->pFirstCtx;
}
ErrorHandler::ErrorHandler()
{
pImpl=new ErrHdl_Impl;
EDcrData *pData=EDcrData::GetData();
ErrorHandler *&pHdl=pData->pFirstHdl;
pImpl->pNext=pHdl;
pHdl=this;
if(!pData->pDsp)
RegisterDisplay(&aDspFunc);
}
ErrorHandler::~ErrorHandler()
{
ErrorHandler **ppHdl=&(EDcrData::GetData()->pFirstHdl);
while(*ppHdl && *ppHdl!=this)
ppHdl=&((*ppHdl)->pImpl->pNext);
if(*ppHdl)
*ppHdl=(*ppHdl)->pImpl->pNext;
delete pImpl;
}
void ErrorHandler::RegisterDisplay(WindowDisplayErrorFunc *aDsp)
{
EDcrData *pData=EDcrData::GetData();
pData->bIsWindowDsp=sal_True;
pData->pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
}
void ErrorHandler::RegisterDisplay(BasicDisplayErrorFunc *aDsp)
{
EDcrData *pData=EDcrData::GetData();
pData->bIsWindowDsp=sal_False;
pData->pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
}
sal_uInt16 ErrorHandler::HandleError_Impl(
sal_uIntPtr lId, sal_uInt16 nFlags, sal_Bool bJustCreateString, String & rError)
{
/* [Beschreibung]
Handelt einen Fehler ab. lId ist die FehlerId, nFlags sind die
ErrorFlags. Werden nFlags nicht abgegeben, so werden die in
der DynamicErrorInfo angegebenen Flags bzw. die aus der Resource
verwendet.
Also:
1. nFlags,
2. Resource Flags
3. Dynamic Flags
4. Default ERRCODE_BUTTON_OK, ERRCODE_MSG_ERROR
*/
String aErr;
String aAction;
if(!lId || lId == ERRCODE_ABORT)
return 0;
EDcrData *pData=EDcrData::GetData();
ErrorInfo *pInfo=ErrorInfo::GetErrorInfo(lId);
ErrorContext *pCtx=ErrorContext::GetContext();
if(pCtx)
pCtx->GetString(pInfo->GetErrorCode(), aAction);
Window *pParent=0;
//Nimm den Parent aus dem Konext
for(;pCtx;pCtx=pCtx->pNext)
if(pCtx->GetParent())
{
pParent=pCtx->GetParent();
break;
}
sal_Bool bWarning = ((lId & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK);
sal_uInt16 nErrFlags = ERRCODE_BUTTON_DEF_OK | ERRCODE_BUTTON_OK;
if (bWarning)
nErrFlags |= ERRCODE_MSG_WARNING;
else
nErrFlags |= ERRCODE_MSG_ERROR;
DynamicErrorInfo* pDynPtr=PTR_CAST(DynamicErrorInfo,pInfo);
if(pDynPtr)
{
sal_uInt16 nDynFlags = pDynPtr->GetDialogMask();
if( nDynFlags )
nErrFlags = nDynFlags;
}
if(ErrHdl_Impl::CreateString(pData->pFirstHdl,pInfo,aErr,nErrFlags))
{
if (bJustCreateString)
{
rError = aErr;
return 1;
}
else
{
if(!pData->pDsp)
{
ByteString aStr("Action: ");
aStr += ByteString( aAction, RTL_TEXTENCODING_ASCII_US );
aStr += ByteString("\nFehler: ");
aStr += ByteString( aErr, RTL_TEXTENCODING_ASCII_US );
DBG_ERROR( aStr.GetBuffer() );
}
else
{
delete pInfo;
if(!pData->bIsWindowDsp)
{
(*(BasicDisplayErrorFunc*)pData->pDsp)(aErr,aAction);
return 0;
}
else
{
if( nFlags != USHRT_MAX )
nErrFlags = nFlags;
return (*(WindowDisplayErrorFunc*)pData->pDsp)(
pParent, nErrFlags, aErr, aAction);
}
}
}
}
DBG_ERROR("Error nicht behandelt");
// Error 1 ist General Error im Sfx
if(pInfo->GetErrorCode()!=1) {
HandleError_Impl(1, USHRT_MAX, bJustCreateString, rError);
}
else {
DBG_ERROR("Error 1 nicht gehandeled");
}
delete pInfo;
return 0;
}
// static
sal_Bool ErrorHandler::GetErrorString(sal_uIntPtr lId, String& rStr)
{
return (sal_Bool)HandleError_Impl( lId, USHRT_MAX, sal_True, rStr );
}
sal_uInt16 ErrorHandler::HandleError(sal_uIntPtr lId, sal_uInt16 nFlags)
{
/* [Beschreibung]
Handelt einen Fehler ab. lId ist die FehlerId, nFlags sind die
ErrorFlags. Werden nFlags nicht abgegeben, so werden die in
der DynamicErrorInfo angegebenen Flags bzw. die aus der Resource
verwendet.
Also:
1. nFlags,
2. Resource Flags
3. Dynamic Flags
4. Default ERRCODE_BUTTON_OK, ERRCODE_MSG_ERROR
*/
String aDummy;
return HandleError_Impl( lId, nFlags, sal_False, aDummy );
}
sal_Bool ErrorHandler::ForwCreateString(const ErrorInfo* pInfo, String& rStr, sal_uInt16 &rFlags) const
{
return ErrHdl_Impl::CreateString(this->pImpl->pNext, pInfo, rStr, rFlags);
}
sal_Bool ErrHdl_Impl::CreateString( const ErrorHandler *pStart,
const ErrorInfo* pInfo, String& pStr,
sal_uInt16 &rFlags)
{
for(const ErrorHandler *pHdl=pStart;pHdl;pHdl=pHdl->pImpl->pNext)
{
if(pHdl->CreateString( pInfo, pStr, rFlags))
return sal_True;
}
return sal_False;
}
sal_Bool SimpleErrorHandler::CreateString(
const ErrorInfo *pInfo, String &rStr, sal_uInt16 &) const
{
sal_uIntPtr nId = pInfo->GetErrorCode();
ByteString aStr;
aStr="Id ";
aStr+=ByteString::CreateFromInt32(nId);
aStr+=" only handled by SimpleErrorHandler";
aStr+="\nErrorCode: ";
aStr+=ByteString::CreateFromInt32(nId & ((1L << ERRCODE_CLASS_SHIFT) - 1 ));
aStr+="\nErrorClass: ";
aStr+=ByteString::CreateFromInt32((nId & ERRCODE_CLASS_MASK) >> ERRCODE_CLASS_SHIFT);
aStr+="\nErrorArea: ";
aStr+=ByteString::CreateFromInt32((nId & ERRCODE_ERROR_MASK &
~((1 << ERRCODE_AREA_SHIFT ) -1 ) ) >> ERRCODE_AREA_SHIFT);
DynamicErrorInfo *pDyn=PTR_CAST(DynamicErrorInfo,pInfo);
if(pDyn)
{
aStr+="\nDId ";
aStr+=ByteString::CreateFromInt32((sal_uIntPtr)*pDyn);
}
StandardErrorInfo *pStd=PTR_CAST(StandardErrorInfo,pInfo);
if(pStd)
{
aStr+="\nXId ";
aStr+=ByteString::CreateFromInt32(pStd->GetExtendedErrorCode());
}
rStr = String( aStr, RTL_TEXTENCODING_ASCII_US );
return sal_True;
}
SimpleErrorHandler::SimpleErrorHandler()
: ErrorHandler()
{
}