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