xref: /aoo41x/main/tools/source/ref/errinf.cxx (revision cdf0e10c)
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