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_svtools.hxx" 30 #include <vos/mutex.hxx> 31 #include <tools/debug.hxx> 32 #include <tools/rcid.h> 33 #include <tools/wintypes.hxx> 34 #include <vcl/msgbox.hxx> 35 #include <vcl/svapp.hxx> 36 #if defined(OS2) 37 #include <vcl/sound.hxx> 38 #endif 39 40 #ifndef GCC 41 #endif 42 43 #include <svtools/ehdl.hxx> 44 #include <svtools/svtdata.hxx> 45 #include <svtools/svtools.hrc> 46 #include <svtools/sfxecode.hxx> 47 48 //========================================================================= 49 50 static sal_uInt16 aWndFunc( 51 Window *pWin, // Parent des Dialoges 52 sal_uInt16 nFlags, 53 const String &rErr, // Fehlertext 54 const String &rAction) // Actiontext 55 56 /* [Beschreibung] 57 58 Bringt eine Fehlerbox auf den Schirm. Je nach nFlags werden 59 Error/ Info usw. Boxen mit den gewuenschten Buttons angezeigt 60 61 Rueckgabewert ist der gedrueckte Button 62 63 */ 64 65 66 { 67 vos:: OGuard aGuard( Application::GetSolarMutex() ); 68 69 // aus den Flags die benoetigten WinBits ermitteln 70 WinBits eBits=0; 71 if ( (ERRCODE_BUTTON_CANCEL|ERRCODE_BUTTON_RETRY) == (nFlags & (ERRCODE_BUTTON_CANCEL|ERRCODE_BUTTON_RETRY)) ) 72 eBits = WB_RETRY_CANCEL; 73 else if ( ERRCODE_BUTTON_OK_CANCEL == (nFlags & ERRCODE_BUTTON_OK_CANCEL) ) 74 eBits = WB_OK_CANCEL; 75 else if ( ERRCODE_BUTTON_OK == (nFlags & ERRCODE_BUTTON_OK) ) 76 eBits = WB_OK; 77 else if ( ERRCODE_BUTTON_YES_NO_CANCEL == (nFlags & ERRCODE_BUTTON_YES_NO_CANCEL) ) 78 eBits = WB_YES_NO_CANCEL; 79 else if ( ERRCODE_BUTTON_YES_NO == (nFlags & ERRCODE_BUTTON_YES_NO) ) 80 eBits = WB_YES_NO; 81 82 switch(nFlags & 0x0f00) 83 { 84 case ERRCODE_BUTTON_DEF_OK: 85 eBits |= WB_DEF_OK; 86 break; 87 88 case ERRCODE_BUTTON_DEF_CANCEL: 89 eBits |= WB_DEF_CANCEL; 90 break; 91 92 case ERRCODE_BUTTON_DEF_YES: 93 eBits |= WB_DEF_YES; 94 break; 95 96 case ERRCODE_BUTTON_DEF_NO: 97 eBits |= WB_DEF_NO; 98 break; 99 } 100 101 String aErr(SvtResId(STR_ERR_HDLMESS)); 102 String aAction(rAction); 103 if ( aAction.Len() ) 104 aAction += String::CreateFromAscii( ":\n" ); 105 aErr.SearchAndReplace(String::CreateFromAscii( "$(ACTION)" ), aAction); 106 aErr.SearchAndReplace(String::CreateFromAscii( "$(ERROR)" ), rErr); 107 108 MessBox* pBox; 109 switch ( nFlags & 0xf000 ) 110 { 111 case ERRCODE_MSG_ERROR: 112 pBox = new ErrorBox(pWin, eBits, aErr); 113 break; 114 115 case ERRCODE_MSG_WARNING: 116 pBox = new WarningBox(pWin, eBits, aErr); 117 break; 118 119 case ERRCODE_MSG_INFO: 120 pBox = new InfoBox(pWin, aErr); 121 break; 122 123 case ERRCODE_MSG_QUERY: 124 pBox = new QueryBox(pWin, eBits, aErr); 125 break; 126 127 default: 128 { 129 DBG_ERRORFILE( "no MessBox type"); 130 pBox = NULL; 131 return ERRCODE_BUTTON_OK; 132 } 133 } 134 135 sal_uInt16 nRet = RET_CANCEL; 136 switch ( pBox->Execute() ) 137 { 138 case RET_OK: 139 nRet = ERRCODE_BUTTON_OK; 140 break; 141 case RET_CANCEL: 142 nRet = ERRCODE_BUTTON_CANCEL; 143 break; 144 case RET_RETRY: 145 nRet = ERRCODE_BUTTON_RETRY; 146 break; 147 case RET_YES: 148 nRet = ERRCODE_BUTTON_YES; 149 break; 150 case RET_NO: 151 nRet = ERRCODE_BUTTON_NO; 152 break; 153 default: 154 DBG_ERRORFILE( "Unknown MessBox return value" ); 155 break; 156 } 157 delete pBox; 158 return nRet; 159 } 160 161 //------------------------------------------------------------------------- 162 163 SfxErrorHandler::SfxErrorHandler(sal_uInt16 nIdP, sal_uLong lStartP, sal_uLong lEndP, ResMgr *pMgrP) : 164 165 lStart(lStartP), lEnd(lEndP), nId(nIdP), pMgr(pMgrP), pFreeMgr( NULL ) 166 167 { 168 RegisterDisplay(&aWndFunc); 169 if( ! pMgr ) 170 { 171 com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); 172 pFreeMgr = pMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(ofa), aLocale ); 173 } 174 } 175 176 //------------------------------------------------------------------------- 177 178 SfxErrorHandler::~SfxErrorHandler() 179 { 180 if( pFreeMgr ) 181 delete pFreeMgr; 182 } 183 184 //------------------------------------------------------------------------- 185 186 sal_Bool SfxErrorHandler::CreateString( 187 const ErrorInfo *pErr, String &rStr, sal_uInt16& nFlags) const 188 189 /* [Beschreibung] 190 191 Der Fehlerstring fuer die ErrorInfo pErr wird zusammengesetzt. 192 193 */ 194 195 { 196 sal_uLong nErrCode = pErr->GetErrorCode() & ERRCODE_ERROR_MASK; 197 if( nErrCode>=lEnd || nErrCode<=lStart ) 198 return sal_False; 199 MessageInfo *pMsgInfo=PTR_CAST(MessageInfo,pErr); 200 if(pMsgInfo) 201 { 202 if(GetMessageString(nErrCode, rStr, nFlags)) 203 { 204 for (xub_StrLen i = 0; i < rStr.Len();) 205 { 206 i = rStr.SearchAndReplace(String::CreateFromAscii( "$(ARG1)" ), 207 pMsgInfo->GetMessageArg(), i); 208 if (i == STRING_NOTFOUND) 209 break; 210 i = i + pMsgInfo->GetMessageArg().Len(); 211 } 212 return sal_True; 213 } 214 } 215 else if(GetErrorString(nErrCode, rStr, nFlags)) 216 { 217 StringErrorInfo *pStringInfo=PTR_CAST(StringErrorInfo,pErr); 218 if(pStringInfo) 219 for (xub_StrLen i = 0; i < rStr.Len();) 220 { 221 i = rStr.SearchAndReplace(String::CreateFromAscii( "$(ARG1)" ), 222 pStringInfo->GetErrorString(), i); 223 if (i == STRING_NOTFOUND) 224 break; 225 i = i + pStringInfo->GetErrorString().Len(); 226 } 227 else 228 { 229 TwoStringErrorInfo * pTwoStringInfo = PTR_CAST(TwoStringErrorInfo, 230 pErr); 231 if (pTwoStringInfo) 232 for (sal_uInt16 i = 0; i < rStr.Len();) 233 { 234 sal_uInt16 nArg1Pos = rStr.Search(String::CreateFromAscii( "$(ARG1)" ), i); 235 sal_uInt16 nArg2Pos = rStr.Search(String::CreateFromAscii( "$(ARG2)" ), i); 236 if (nArg1Pos < nArg2Pos) 237 { 238 rStr.Replace(nArg1Pos, 7, pTwoStringInfo->GetArg1()); 239 i = nArg1Pos + pTwoStringInfo->GetArg1().Len(); 240 } 241 else if (nArg2Pos < nArg1Pos) 242 { 243 rStr.Replace(nArg2Pos, 7, pTwoStringInfo->GetArg2()); 244 i = nArg2Pos + pTwoStringInfo->GetArg2().Len(); 245 } 246 else break; 247 } 248 } 249 return sal_True; 250 } 251 return sal_False; 252 } 253 254 //------------------------------------------------------------------------- 255 256 class ResString: public String 257 258 /* [Beschreibung] 259 260 Hilfsklasse zum Auslesen eines Strings und optionaler ExtraData aus 261 einer String Resource. 262 263 */ 264 265 { 266 sal_uInt16 nFlags; 267 public: 268 sal_uInt16 GetFlags() const {return nFlags;} 269 const String & GetString() const {return *this;} 270 ResString( ResId &rId); 271 }; 272 273 //------------------------------------------------------------------------- 274 275 ResString::ResString(ResId & rId): 276 String(rId.SetAutoRelease(sal_False)), 277 nFlags(0) 278 { 279 ResMgr * pResMgr = rId.GetResMgr(); 280 // String ctor temporarily sets global ResManager 281 if (pResMgr->GetRemainSize()) 282 nFlags = sal_uInt16(pResMgr->ReadShort()); 283 rId.SetAutoRelease(sal_True); 284 pResMgr->PopContext(); 285 } 286 287 //------------------------------------------------------------------------- 288 289 struct ErrorResource_Impl : private Resource 290 291 /* [Beschreibung] 292 293 Hilfsklasse zum Zugriff auf String SubResourcen einer Resource 294 */ 295 296 { 297 298 ResId aResId; 299 300 ErrorResource_Impl(ResId& rErrIdP, sal_uInt16 nId) 301 : Resource(rErrIdP),aResId(nId,*rErrIdP.GetResMgr()){} 302 303 ~ErrorResource_Impl() { FreeResource(); } 304 305 operator ResString(){ return ResString( aResId ); } 306 operator sal_Bool(){return IsAvailableRes(aResId.SetRT(RSC_STRING));} 307 308 }; 309 310 311 sal_Bool SfxErrorHandler::GetClassString(sal_uLong lClassId, String &rStr) const 312 313 /* [Beschreibung] 314 315 Erzeugt den String fuer die Klasse des Fehlers. Wird immer aus der 316 Resource des Sfx gelesen 317 318 */ 319 320 { 321 sal_Bool bRet = sal_False; 322 com::sun::star::lang::Locale aLocale( Application::GetSettings().GetUILocale() ); 323 ResMgr* pResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(ofa), aLocale ); 324 if( pResMgr ) 325 { 326 ResId aId(RID_ERRHDL, *pResMgr ); 327 ErrorResource_Impl aEr(aId, (sal_uInt16)lClassId); 328 if(aEr) 329 { 330 rStr=((ResString)aEr).GetString(); 331 bRet = sal_True; 332 } 333 } 334 delete pResMgr; 335 return bRet; 336 } 337 338 //------------------------------------------------------------------------- 339 340 sal_Bool SfxErrorHandler::GetMessageString( 341 sal_uLong lErrId, String &rStr, sal_uInt16 &nFlags) const 342 343 /* [Beschreibung] 344 345 Erzeugt den String fuer die Ausgabe in einer MessageBox 346 347 */ 348 349 { 350 sal_Bool bRet = sal_False; 351 ResId *pResId= new ResId(nId, *pMgr); 352 353 ErrorResource_Impl aEr(*pResId, (sal_uInt16)lErrId); 354 if(aEr) 355 { 356 ResString aErrorString(aEr); 357 sal_uInt16 nResFlags = aErrorString.GetFlags(); 358 if( nResFlags ) 359 nFlags=aErrorString.GetFlags(); 360 rStr = aErrorString.GetString(); 361 bRet = sal_True; 362 } 363 364 delete pResId; 365 return bRet; 366 } 367 368 //------------------------------------------------------------------------- 369 370 sal_Bool SfxErrorHandler::GetErrorString( 371 sal_uLong lErrId, String &rStr, sal_uInt16 &nFlags) const 372 373 /* [Beschreibung] 374 Erzeugt den Fehlerstring fuer den eigentlichen Fehler ohne 375 dessen Klasse 376 377 */ 378 379 { 380 vos:: OGuard aGuard( Application::GetSolarMutex() ); 381 382 sal_Bool bRet = sal_False; 383 rStr=String(SvtResId(RID_ERRHDL_CLASS)); 384 ResId aResId(nId, *pMgr); 385 386 { 387 ErrorResource_Impl aEr(aResId, (sal_uInt16)lErrId); 388 if(aEr) 389 { 390 ResString aErrorString(aEr); 391 392 sal_uInt16 nResFlags = aErrorString.GetFlags(); 393 if ( nResFlags ) 394 nFlags = nResFlags; 395 rStr.SearchAndReplace( 396 String::CreateFromAscii("$(ERROR)"), aErrorString.GetString()); 397 bRet = sal_True; 398 } 399 else 400 bRet = sal_False; 401 } 402 403 if( bRet ) 404 { 405 String aErrStr; 406 GetClassString(lErrId & ERRCODE_CLASS_MASK, 407 aErrStr); 408 if(aErrStr.Len()) 409 aErrStr+=String::CreateFromAscii( ".\n" ); 410 rStr.SearchAndReplace(String::CreateFromAscii( "$(CLASS)" ),aErrStr); 411 } 412 413 return bRet; 414 } 415 416 //------------------------------------------------------------------------- 417 418 SfxErrorContext::SfxErrorContext( 419 sal_uInt16 nCtxIdP, Window *pWindow, sal_uInt16 nResIdP, ResMgr *pMgrP) 420 : ErrorContext(pWindow), nCtxId(nCtxIdP), nResId(nResIdP), pMgr(pMgrP) 421 { 422 if( nResId==USHRT_MAX ) 423 nResId=RID_ERRCTX; 424 } 425 426 //------------------------------------------------------------------------- 427 428 SfxErrorContext::SfxErrorContext( 429 sal_uInt16 nCtxIdP, const String &aArg1P, Window *pWindow, 430 sal_uInt16 nResIdP, ResMgr *pMgrP) 431 : ErrorContext(pWindow), nCtxId(nCtxIdP), nResId(nResIdP), pMgr(pMgrP), 432 aArg1(aArg1P) 433 { 434 if( nResId==USHRT_MAX ) 435 nResId=RID_ERRCTX; 436 } 437 438 //------------------------------------------------------------------------- 439 440 sal_Bool SfxErrorContext::GetString(sal_uLong nErrId, String &rStr) 441 442 /* [Beschreibung] 443 444 Baut die Beschreibung eines ErrorContextes auf 445 */ 446 447 { 448 bool bRet = false; 449 ResMgr* pFreeMgr = NULL; 450 if( ! pMgr ) 451 { 452 com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); 453 pFreeMgr = pMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(ofa), aLocale ); 454 } 455 if( pMgr ) 456 { 457 vos:: OGuard aGuard( Application::GetSolarMutex() ); 458 459 ResId aResId( nResId, *pMgr ); 460 461 ErrorResource_Impl aTestEr( aResId, nCtxId ); 462 if ( aTestEr ) 463 { 464 rStr = ( (ResString)aTestEr ).GetString(); 465 rStr.SearchAndReplace( String::CreateFromAscii( "$(ARG1)" ), aArg1 ); 466 bRet = true; 467 } 468 else 469 { 470 DBG_ERRORFILE( "ErrorContext cannot find the resource" ); 471 bRet = false; 472 } 473 474 if ( bRet ) 475 { 476 sal_uInt16 nId = ( nErrId & ERRCODE_WARNING_MASK ) ? ERRCTX_WARNING : ERRCTX_ERROR; 477 ResId aSfxResId( RID_ERRCTX, *pMgr ); 478 ErrorResource_Impl aEr( aSfxResId, nId ); 479 rStr.SearchAndReplace( String::CreateFromAscii( "$(ERR)" ), ( (ResString)aEr ).GetString() ); 480 } 481 } 482 483 if( pFreeMgr ) 484 { 485 delete pFreeMgr; 486 pMgr = NULL; 487 } 488 return bRet; 489 } 490