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