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
EDcrData()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
GetData()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
RegisterEDcr(DynamicErrorInfo * pDcr)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
UnRegisterEDcr(DynamicErrorInfo * pDcr)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
GetErrorInfo(sal_uIntPtr lId)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
operator sal_uIntPtr() const149 DynamicErrorInfo::operator sal_uIntPtr() const
150 {
151 return pImpl->lErrId;
152 }
153
DynamicErrorInfo(sal_uIntPtr lArgUserId,sal_uInt16 nMask)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
~DynamicErrorInfo()162 DynamicErrorInfo::~DynamicErrorInfo()
163 {
164 pImpl->UnRegisterEDcr(this);
165 delete pImpl;
166 }
167
GetDynamicErrorInfo(sal_uIntPtr lId)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
GetDialogMask() const179 sal_uInt16 DynamicErrorInfo::GetDialogMask() const
180 {
181 return pImpl->nMask;
182 }
183
184
StandardErrorInfo(sal_uIntPtr UserId,sal_uIntPtr lArgExtId,sal_uInt16 nFlags)185 StandardErrorInfo::StandardErrorInfo(
186 sal_uIntPtr UserId, sal_uIntPtr lArgExtId, sal_uInt16 nFlags)
187 : DynamicErrorInfo(UserId, nFlags), lExtId(lArgExtId)
188 {
189 }
190
191
StringErrorInfo(sal_uIntPtr UserId,const String & aStringP,sal_uInt16 nFlags)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
aDspFunc(const String & rErr,const String & rAction)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
ErrorContext(Window * pWinP)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
~ErrorContext()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
GetContext()237 ErrorContext *ErrorContext::GetContext()
238 {
239 return EDcrData::GetData()->pFirstCtx;
240 }
241
ErrorHandler()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
~ErrorHandler()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
RegisterDisplay(WindowDisplayErrorFunc * aDsp)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
RegisterDisplay(BasicDisplayErrorFunc * aDsp)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
HandleError_Impl(sal_uIntPtr lId,sal_uInt16 nFlags,sal_Bool bJustCreateString,String & rError)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
GetErrorString(sal_uIntPtr lId,String & rStr)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
HandleError(sal_uIntPtr lId,sal_uInt16 nFlags)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
ForwCreateString(const ErrorInfo * pInfo,String & rStr,sal_uInt16 & rFlags) const406 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
CreateString(const ErrorHandler * pStart,const ErrorInfo * pInfo,String & pStr,sal_uInt16 & rFlags)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
CreateString(const ErrorInfo * pInfo,String & rStr,sal_uInt16 &) const423 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
SimpleErrorHandler()454 SimpleErrorHandler::SimpleErrorHandler()
455 : ErrorHandler()
456 {
457 }
458
459