1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_tools.hxx" 30 31 #include <limits.h> 32 #include <tools/shl.hxx> 33 #include <tools/debug.hxx> 34 #include <tools/errinf.hxx> 35 #include <tools/string.hxx> 36 37 class ErrorHandler; 38 39 namespace { 40 41 typedef void (* DisplayFnPtr)(); 42 43 } 44 45 struct EDcrData 46 { 47 public: 48 49 ErrorHandler *pFirstHdl; 50 ErrorContext *pFirstCtx; 51 DisplayFnPtr pDsp; 52 sal_Bool bIsWindowDsp; 53 54 55 DynamicErrorInfo *ppDcr[ERRCODE_DYNAMIC_COUNT]; 56 sal_uInt16 nNextDcr; 57 EDcrData(); 58 59 static EDcrData *GetData(); 60 61 }; 62 63 class EDcr_Impl 64 { 65 sal_uIntPtr lErrId; 66 sal_uInt16 nMask; 67 68 void RegisterEDcr(DynamicErrorInfo *); 69 void UnRegisterEDcr(DynamicErrorInfo *); 70 static ErrorInfo *GetDynamicErrorInfo(sal_uIntPtr lId); 71 72 friend class DynamicErrorInfo; 73 friend class ErrorInfo; 74 }; 75 76 77 EDcrData::EDcrData() 78 { 79 for(sal_uInt16 n=0;n<ERRCODE_DYNAMIC_COUNT;n++) 80 ppDcr[n]=0; 81 nNextDcr=0; 82 pFirstHdl=0; 83 pDsp=0; 84 pFirstCtx=0; 85 } 86 87 88 EDcrData *EDcrData::GetData() 89 { 90 #ifdef BOOTSTRAP 91 return 0x0; 92 #else 93 EDcrData **ppDat=(EDcrData **)GetAppData(SHL_ERR); 94 if(!*ppDat) 95 { 96 return (*ppDat=new EDcrData); 97 } 98 else 99 return *ppDat; 100 #endif 101 } 102 103 void EDcr_Impl::RegisterEDcr(DynamicErrorInfo *pDcr) 104 { 105 //Vergibt eine dynamische Id 106 107 EDcrData* pData=EDcrData::GetData(); 108 lErrId= (((sal_uIntPtr)pData->nNextDcr + 1) << ERRCODE_DYNAMIC_SHIFT) + 109 pDcr->GetErrorCode(); 110 DynamicErrorInfo **ppDcr=pData->ppDcr; 111 sal_uInt16 nNext=pData->nNextDcr; 112 113 // bei einem Ringbuffer koennen wir uns das ASSERT wohl sparen! 114 // DBG_ASSERT(ppDcr[nNext]==0,"ErrHdl: Alle Errors belegt"); 115 if(ppDcr[nNext]) 116 { 117 delete ppDcr[nNext]; 118 } 119 ppDcr[nNext]=pDcr; 120 if(++pData->nNextDcr>=ERRCODE_DYNAMIC_COUNT) 121 pData->nNextDcr=0; 122 } 123 124 125 void EDcr_Impl::UnRegisterEDcr(DynamicErrorInfo *pDcr) 126 { 127 128 EDcrData* pData=EDcrData::GetData(); 129 DynamicErrorInfo **ppDcr=pData->ppDcr; 130 sal_uIntPtr lIdx=( 131 ((sal_uIntPtr)(*pDcr) & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1; 132 DBG_ASSERT(ppDcr[lIdx]==pDcr,"ErrHdl: Error nicht gefunden"); 133 if(ppDcr[lIdx]==pDcr) 134 ppDcr[lIdx]=0; 135 } 136 137 TYPEINIT0(ErrorInfo); 138 TYPEINIT1(DynamicErrorInfo, ErrorInfo); 139 TYPEINIT1(StandardErrorInfo, DynamicErrorInfo); 140 TYPEINIT1(StringErrorInfo, DynamicErrorInfo); 141 TYPEINIT1(TwoStringErrorInfo, DynamicErrorInfo); 142 TYPEINIT1(MessageInfo, DynamicErrorInfo); 143 144 145 ErrorInfo *ErrorInfo::GetErrorInfo(sal_uIntPtr lId) 146 { 147 if(lId & ERRCODE_DYNAMIC_MASK) 148 return EDcr_Impl::GetDynamicErrorInfo(lId); 149 else 150 return new ErrorInfo(lId); 151 } 152 153 DynamicErrorInfo::operator sal_uIntPtr() const 154 { 155 return pImpl->lErrId; 156 } 157 158 DynamicErrorInfo::DynamicErrorInfo(sal_uIntPtr lArgUserId, sal_uInt16 nMask) 159 : ErrorInfo(lArgUserId) 160 { 161 pImpl=new EDcr_Impl; 162 pImpl->RegisterEDcr(this); 163 pImpl->nMask=nMask; 164 } 165 166 DynamicErrorInfo::~DynamicErrorInfo() 167 { 168 pImpl->UnRegisterEDcr(this); 169 delete pImpl; 170 } 171 172 ErrorInfo* EDcr_Impl::GetDynamicErrorInfo(sal_uIntPtr lId) 173 { 174 sal_uIntPtr lIdx=((lId & ERRCODE_DYNAMIC_MASK)>>ERRCODE_DYNAMIC_SHIFT)-1; 175 DynamicErrorInfo* pDcr=EDcrData::GetData()->ppDcr[lIdx]; 176 if(pDcr && (sal_uIntPtr)(*pDcr)==lId) 177 return pDcr; 178 else 179 return new ErrorInfo(lId & ~ERRCODE_DYNAMIC_MASK); 180 } 181 182 183 sal_uInt16 DynamicErrorInfo::GetDialogMask() const 184 { 185 return pImpl->nMask; 186 } 187 188 189 StandardErrorInfo::StandardErrorInfo( 190 sal_uIntPtr UserId, sal_uIntPtr lArgExtId, sal_uInt16 nFlags) 191 : DynamicErrorInfo(UserId, nFlags), lExtId(lArgExtId) 192 { 193 } 194 195 196 StringErrorInfo::StringErrorInfo( 197 sal_uIntPtr UserId, const String& aStringP, sal_uInt16 nFlags) 198 : DynamicErrorInfo(UserId, nFlags), aString(aStringP) 199 { 200 } 201 202 203 class ErrHdl_Impl 204 { 205 public: 206 207 ErrorHandler *pNext; 208 static sal_Bool CreateString(const ErrorHandler *pStart, 209 const ErrorInfo*, String&, sal_uInt16&); 210 }; 211 212 213 static void aDspFunc(const String &rErr, const String &rAction) 214 { 215 ByteString aErr("Aktion: "); 216 aErr+= ByteString( rAction, RTL_TEXTENCODING_ASCII_US ); 217 aErr+=" Fehler: "; 218 aErr+= ByteString( rErr, RTL_TEXTENCODING_ASCII_US ); 219 DBG_ERROR(aErr.GetBuffer()); 220 } 221 222 223 ErrorContext::ErrorContext(Window *pWinP) 224 { 225 EDcrData *pData=EDcrData::GetData(); 226 ErrorContext *&pHdl=pData->pFirstCtx; 227 pWin=pWinP; 228 pNext=pHdl; 229 pHdl=this; 230 } 231 232 ErrorContext::~ErrorContext() 233 { 234 ErrorContext **ppCtx=&(EDcrData::GetData()->pFirstCtx); 235 while(*ppCtx && *ppCtx!=this) 236 ppCtx=&((*ppCtx)->pNext); 237 if(*ppCtx) 238 *ppCtx=(*ppCtx)->pNext; 239 } 240 241 ErrorContext *ErrorContext::GetContext() 242 { 243 return EDcrData::GetData()->pFirstCtx; 244 } 245 246 ErrorHandler::ErrorHandler() 247 { 248 pImpl=new ErrHdl_Impl; 249 EDcrData *pData=EDcrData::GetData(); 250 ErrorHandler *&pHdl=pData->pFirstHdl; 251 pImpl->pNext=pHdl; 252 pHdl=this; 253 if(!pData->pDsp) 254 RegisterDisplay(&aDspFunc); 255 } 256 257 ErrorHandler::~ErrorHandler() 258 { 259 ErrorHandler **ppHdl=&(EDcrData::GetData()->pFirstHdl); 260 while(*ppHdl && *ppHdl!=this) 261 ppHdl=&((*ppHdl)->pImpl->pNext); 262 if(*ppHdl) 263 *ppHdl=(*ppHdl)->pImpl->pNext; 264 delete pImpl; 265 } 266 267 void ErrorHandler::RegisterDisplay(WindowDisplayErrorFunc *aDsp) 268 { 269 EDcrData *pData=EDcrData::GetData(); 270 pData->bIsWindowDsp=sal_True; 271 pData->pDsp = reinterpret_cast< DisplayFnPtr >(aDsp); 272 } 273 274 void ErrorHandler::RegisterDisplay(BasicDisplayErrorFunc *aDsp) 275 { 276 EDcrData *pData=EDcrData::GetData(); 277 pData->bIsWindowDsp=sal_False; 278 pData->pDsp = reinterpret_cast< DisplayFnPtr >(aDsp); 279 } 280 281 sal_uInt16 ErrorHandler::HandleError_Impl( 282 sal_uIntPtr lId, sal_uInt16 nFlags, sal_Bool bJustCreateString, String & rError) 283 { 284 285 /* [Beschreibung] 286 Handelt einen Fehler ab. lId ist die FehlerId, nFlags sind die 287 ErrorFlags. Werden nFlags nicht abgegeben, so werden die in 288 der DynamicErrorInfo angegebenen Flags bzw. die aus der Resource 289 verwendet. 290 291 Also: 292 293 1. nFlags, 294 2. Resource Flags 295 3. Dynamic Flags 296 4. Default ERRCODE_BUTTON_OK, ERRCODE_MSG_ERROR 297 298 299 */ 300 301 String aErr; 302 String aAction; 303 if(!lId || lId == ERRCODE_ABORT) 304 return 0; 305 EDcrData *pData=EDcrData::GetData(); 306 ErrorInfo *pInfo=ErrorInfo::GetErrorInfo(lId); 307 ErrorContext *pCtx=ErrorContext::GetContext(); 308 if(pCtx) 309 pCtx->GetString(pInfo->GetErrorCode(), aAction); 310 Window *pParent=0; 311 //Nimm den Parent aus dem Konext 312 for(;pCtx;pCtx=pCtx->pNext) 313 if(pCtx->GetParent()) 314 { 315 pParent=pCtx->GetParent(); 316 break; 317 } 318 319 sal_Bool bWarning = ((lId & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK); 320 sal_uInt16 nErrFlags = ERRCODE_BUTTON_DEF_OK | ERRCODE_BUTTON_OK; 321 if (bWarning) 322 nErrFlags |= ERRCODE_MSG_WARNING; 323 else 324 nErrFlags |= ERRCODE_MSG_ERROR; 325 326 DynamicErrorInfo* pDynPtr=PTR_CAST(DynamicErrorInfo,pInfo); 327 if(pDynPtr) 328 { 329 sal_uInt16 nDynFlags = pDynPtr->GetDialogMask(); 330 if( nDynFlags ) 331 nErrFlags = nDynFlags; 332 } 333 334 if(ErrHdl_Impl::CreateString(pData->pFirstHdl,pInfo,aErr,nErrFlags)) 335 { 336 if (bJustCreateString) 337 { 338 rError = aErr; 339 return 1; 340 } 341 else 342 { 343 if(!pData->pDsp) 344 { 345 ByteString aStr("Action: "); 346 aStr += ByteString( aAction, RTL_TEXTENCODING_ASCII_US ); 347 aStr += ByteString("\nFehler: "); 348 aStr += ByteString( aErr, RTL_TEXTENCODING_ASCII_US ); 349 DBG_ERROR( aStr.GetBuffer() ); 350 } 351 else 352 { 353 delete pInfo; 354 if(!pData->bIsWindowDsp) 355 { 356 (*(BasicDisplayErrorFunc*)pData->pDsp)(aErr,aAction); 357 return 0; 358 } 359 else 360 { 361 if( nFlags != USHRT_MAX ) 362 nErrFlags = nFlags; 363 return (*(WindowDisplayErrorFunc*)pData->pDsp)( 364 pParent, nErrFlags, aErr, aAction); 365 } 366 } 367 } 368 } 369 DBG_ERROR("Error nicht behandelt"); 370 // Error 1 ist General Error im Sfx 371 if(pInfo->GetErrorCode()!=1) { 372 HandleError_Impl(1, USHRT_MAX, bJustCreateString, rError); 373 } 374 else { 375 DBG_ERROR("Error 1 nicht gehandeled"); 376 } 377 delete pInfo; 378 return 0; 379 } 380 381 // static 382 sal_Bool ErrorHandler::GetErrorString(sal_uIntPtr lId, String& rStr) 383 { 384 return (sal_Bool)HandleError_Impl( lId, USHRT_MAX, sal_True, rStr ); 385 } 386 387 sal_uInt16 ErrorHandler::HandleError(sal_uIntPtr lId, sal_uInt16 nFlags) 388 { 389 390 /* [Beschreibung] 391 Handelt einen Fehler ab. lId ist die FehlerId, nFlags sind die 392 ErrorFlags. Werden nFlags nicht abgegeben, so werden die in 393 der DynamicErrorInfo angegebenen Flags bzw. die aus der Resource 394 verwendet. 395 396 Also: 397 398 1. nFlags, 399 2. Resource Flags 400 3. Dynamic Flags 401 4. Default ERRCODE_BUTTON_OK, ERRCODE_MSG_ERROR 402 403 404 */ 405 406 String aDummy; 407 return HandleError_Impl( lId, nFlags, sal_False, aDummy ); 408 } 409 410 sal_Bool ErrorHandler::ForwCreateString(const ErrorInfo* pInfo, String& rStr, sal_uInt16 &rFlags) const 411 { 412 return ErrHdl_Impl::CreateString(this->pImpl->pNext, pInfo, rStr, rFlags); 413 } 414 415 sal_Bool ErrHdl_Impl::CreateString( const ErrorHandler *pStart, 416 const ErrorInfo* pInfo, String& pStr, 417 sal_uInt16 &rFlags) 418 { 419 for(const ErrorHandler *pHdl=pStart;pHdl;pHdl=pHdl->pImpl->pNext) 420 { 421 if(pHdl->CreateString( pInfo, pStr, rFlags)) 422 return sal_True; 423 } 424 return sal_False; 425 } 426 427 sal_Bool SimpleErrorHandler::CreateString( 428 const ErrorInfo *pInfo, String &rStr, sal_uInt16 &) const 429 { 430 sal_uIntPtr nId = pInfo->GetErrorCode(); 431 ByteString aStr; 432 aStr="Id "; 433 aStr+=ByteString::CreateFromInt32(nId); 434 aStr+=" only handled by SimpleErrorHandler"; 435 aStr+="\nErrorCode: "; 436 aStr+=ByteString::CreateFromInt32(nId & ((1L << ERRCODE_CLASS_SHIFT) - 1 )); 437 aStr+="\nErrorClass: "; 438 aStr+=ByteString::CreateFromInt32((nId & ERRCODE_CLASS_MASK) >> ERRCODE_CLASS_SHIFT); 439 aStr+="\nErrorArea: "; 440 aStr+=ByteString::CreateFromInt32((nId & ERRCODE_ERROR_MASK & 441 ~((1 << ERRCODE_AREA_SHIFT ) -1 ) ) >> ERRCODE_AREA_SHIFT); 442 DynamicErrorInfo *pDyn=PTR_CAST(DynamicErrorInfo,pInfo); 443 if(pDyn) 444 { 445 aStr+="\nDId "; 446 aStr+=ByteString::CreateFromInt32((sal_uIntPtr)*pDyn); 447 } 448 StandardErrorInfo *pStd=PTR_CAST(StandardErrorInfo,pInfo); 449 if(pStd) 450 { 451 aStr+="\nXId "; 452 aStr+=ByteString::CreateFromInt32(pStd->GetExtendedErrorCode()); 453 } 454 rStr = String( aStr, RTL_TEXTENCODING_ASCII_US ); 455 return sal_True; 456 } 457 458 SimpleErrorHandler::SimpleErrorHandler() 459 : ErrorHandler() 460 { 461 } 462 463